为了账号安全,请及时绑定邮箱和手机立即绑定

通过 ssh 有条件地运行子进程,同时将输出附加到(可能是远程)文件

通过 ssh 有条件地运行子进程,同时将输出附加到(可能是远程)文件

隔江千里 2023-07-11 15:12:10
我有一个可以在我的主机和其他几台服务器上运行的脚本。我想使用 ssh 将此脚本作为我的主机上的后台进程与远程计算机一起启动,并将 stdout/stderr 输出到主机以用于我的主机后台进程,并输出到远程计算机以用于远程计算机后台任务。我尝试过subprocess.check_output(['python' ,'script.py' ,'arg_1', ' > file.log ', ' & echo -ne $! ']但它不起作用。它不给我 pid 也不写入文件。它可以工作shell=True,但后来我读到出于安全原因使用 shell=True 不好。然后我尝试了p = subprocess.Popen(['python' ,'script.py' ,'arg_1', ' > file.log ']现在我可以获得进程 pid,但输出没有写入远程日志文件。使用下面建议的 stdout/stderr 参数将在我的主机而不是远程计算机中打开日志文件。有人可以建议我一个既可以在我的主机上工作,也可以通过 ssh 连接到远程服务器并在那里启动后台进程的命令吗?并写入输出文件?<HOW_TO_GET_PID> = subprocess.<WHAT>( ([] if 'localhost' else ['ssh','<remote_server>']) + ['python', 'script.py', 'arg_1' <WHAT>] )有人可以完成上面的伪代码吗?
查看完整描述

2 回答

?
慕盖茨4494581

TA贡献1850条经验 获得超11个赞

你不可能在一行行中得到安全、正确的东西而不使其不可读。最好不要尝试。


请注意,我们在这里使用 shell:在本地情况下,我们显式调用shell=True,而在远程情况下ssh,总是隐式启动 shell。


import shlex

import subprocess


def startBackgroundCommand(argv, outputFile, remoteHost=None, andGetPID=False):

    cmd_str = ' '.join(shlex.quote(word) for word in argv)

    if outputFile != None:

        cmd_str += ' >%s' % (shlex.quote(outputFile),)

    if andGetPID:

        cmd_str += ' & echo "$!"'

    if remoteHost != None:

        p = subprocess.Popen(['ssh', remoteHost, cmd_str], stdout=subprocess.PIPE)

    else:

        p = subprocess.Popen(cmd_str, stdout=subprocess.PIPE, shell=True)

    return p.communicate()[0]


# Run your command locally

startBackgroundCommand(['python', 'script.py', 'arg_1'],

    outputFile='file.log', andGetPID=True)


# Or run your command remotely

startBackgroundCommand(['python', 'script.py', 'arg_1'],

    remoteHost='foo.example.com', outputFile='file.log', andGetPID=True)


查看完整回答
反对 回复 2023-07-11
?
蓝山帝景

TA贡献1843条经验 获得超7个赞

# At the beginning you can even program automatic daemonizing

# Using os.fork(), otherwise, you run it with something like:

# nohup python run_my_script.py &

# This will ensure that it continues running even if SSH connection breaks.

from subprocess import Popen, PIPE, STDOUT


p = Popen(["python", "yourscript.py"], stdout=PIPE, stderr=STDOUT, stdin=PIPE)

p.stdin.close()

log = open("logfile.log", "wb")

log.write(b"PID: %i\n\n" % p.pid)

while 1:

    line = p.stdout.readline()

    if not line: break

    log.write(line)

    log.flush()


p.stdout.close()

log.write(b"\nExit status: %i" % p.poll())

log.close()


查看完整回答
反对 回复 2023-07-11
  • 2 回答
  • 0 关注
  • 223 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信