[英]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
. 我使用通道捕获STDERR
和STDOUT
。
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: 经过更多测试并感谢注释,我意识到我的代码中存在三个错误:
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. 在这种情况下,我不需要任何这些。 Net::SSH.exec!
waits for the command to complete. 等待命令完成。 I needed to launch and forget. 我需要发射,忘记了。 (Silly mistake) (愚蠢的错误) 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.