J'ai un script qui peut fonctionner sur ma machine hôte et plusieurs autres serveurs. Je souhaite lancer ce script en tant que processus d'arrière-plan sur ma machine hôte avec la machine distante à l'aide de ssh et générer le stdout / stderr vers la machine hôte pour le processus d'arrière-plan de ma machine hôte et sur les machines distantes pour les tâches d'arrière-plan de la machine distante.

J'ai essayé avec

subprocess.check_output(['python' ,'script.py' ,'arg_1', ' > file.log ', ' & echo -ne $! ']

Mais ça ne marche pas. il ne me donne pas le pid ni n'écrit dans le fichier. Cela fonctionne avec shell=True mais j'ai lu que ce n'est pas bon d'utiliser shell = True pour des raisons de sécurité.

Alors j'ai essayé

p = subprocess.Popen(['python' ,'script.py' ,'arg_1', ' > file.log ']

Maintenant, je peux obtenir le processus pid mais la sortie n'écrit pas dans le fichier journal distant.

L'utilisation des arguments stdout / stderr comme suggéré ci-dessous ouvrira le fichier journal sur ma machine hôte et non sur la machine distante. Je veux plutôt me connecter sur la machine distante. ajouter le sous-processus.Ouvrir la sortie dans le fichier?

Quelqu'un pourrait-il s'il vous plaît me suggérer une seule commande qui fonctionne à la fois sur ma machine hôte et également sur le serveur distant ssh et lance le processus d'arrière-plan là-bas? et écrire dans le fichier de sortie?

<HOW_TO_GET_PID> = subprocess.<WHAT>( ([] if 'localhost' else ['ssh','<remote_server>']) + ['python', 'script.py', 'arg_1' <WHAT>] )

Quelqu'un pourrait s'il vous plaît terminer le pseudo code ci-dessus?

Merci,

0
user4772933 3 sept. 2020 à 16:20

2 réponses

Meilleure réponse

Vous n'obtiendrez pas quelque chose de sûr et correct dans une seule ligne sans le rendre illisible; mieux vaut ne pas essayer.

Notez que nous utilisons un shell ici: dans le cas local, nous appelons explicitement shell=True, alors que dans le cas distant ssh toujours, démarre implicitement un 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)
0
Charles Duffy 3 sept. 2020 à 14:59

# 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()

0
Dalen 3 sept. 2020 à 14:08