简体   繁体   English

Ruby Net / SSH-启动远程Python脚本并分离

[英]Ruby Net/SSH - Launch remote Python script and detach

I need to launch a remote Python script through SSH. 我需要通过SSH启动远程Python脚本。 The Python script on the remote machine needs to perform some file manipulation, launch an executable for a simulation (from a few hours to days), collect the results and write to a file. 远程计算机上的Python脚本需要执行一些文件操作,启动仿真可执行文件(从几小时到几天),收集结果并写入文件。

I am launching the script from Ruby using Net-SSH exec! 我正在使用Net-SSH exec!从Ruby启动脚本Net-SSH exec! . I use channels to capture STDERR and STDOUT . 我使用通道捕获STDERRSTDOUT

The script works fine, but now I would like to detach the running script on the remote machine from my local Ruby script. 该脚本可以正常工作,但是现在我想从本地Ruby脚本中分离远程计算机上正在运行的脚本。 I will then check directly on the remote machine the state of the simulation. 然后,我将直接在远程计算机上检查仿真状态。

I have tried to run the script using nohup . 我尝试使用nohup运行脚本。

Net::SSH.exec!("nohup python script.py args > out.log 2> err.log < /dev/null &")

The script is detached and I get back control immediately, but the script on the remote machine gets killed and I cannot find the process in background. 脚本被分离,我立即获得控制权,但是远程计算机上的脚本被杀死,我无法在后台找到该进程。

Ideally I would launch the simulation executable directly from Ruby, but I have to use Python because I need some libraries that are not available in Ruby. 理想情况下,我将直接从Ruby启动模拟可执行文件,但是我必须使用Python,因为我需要一些在Ruby中不可用的库。

Is the approach above correct? 以上方法正确吗? Can I use nohup with Net-SSH? 我可以将nohup与Net-SSH一起使用吗?

Is there a better approach? 有没有更好的方法?

EDIT: 编辑:

  def self.ssh_exec!(ssh, cmd, log = nil)

    ssh.open_channel do |ch|

      ch.request_pty do |chan,success|
      end

      ch.exec(cmd) do |chan, success|
        raise "could not execute command" unless success

        # "on_data" is called when the process writes something to stdout
        chan.on_data do |c, data|
          log ? (log << data) : (puts data) 
        end

        # "on_extended_data" is called when the process writes something to stderr
        chan.on_extended_data do |c, type, data|
          log ? (log.error data) : (puts data) 
        end

        chan.on_close do
           puts 'Done'
        end
      end
    end    
   end  

then I call 然后我打电话

  Net::SSH.start(aws_ip, user, options = aws_options) do |ssh|

    script = File.join(path, 'pyfoam_scripts', 'run_case.py')
    cmd = "source...; python #{script} #{dst_case}"
    RG::Utils.ssh_exec!(ssh, cmd, @logger)

    ssh.loop
  end

where 哪里

:options => {:keys => path_to_key, 'key.pem'), 
                        :keepalive => true,
                        :timeout => 3000, 
                        :compression => true,
                        :compression_level => 6},

After a bit more testing and thanks to the comments I realised that there were three errors in my code: 经过更多测试并感谢注释,我意识到我的代码中存在三个错误:

  1. I was using channels . 我正在使用channels Channels are used to establish a communication with the remote machine, capture the output, use callbacks. Channels用于与远程计算机建立通信,捕获输出,使用回调。 In this case, I didn't need any of this. 在这种情况下,我不需要任何这些。
  2. Net::SSH.exec! waits for the command to complete. 等待命令完成。 I needed to launch and forget. 我需要发射,忘记了。 (Silly mistake) (愚蠢的错误)
  3. ssh.loop is not needed. ssh.loop See 1. 请参阅1。

After fixing the errors above, it works like a charm. 修复上述错误后,它就像一个符咒。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM