J'ai du mal à analyser les arguments de subprocess.Popen. J'essaye d'exécuter un script sur mon serveur Unix. La syntaxe du script lors de l'exécution sur l'invite du shell est la suivante: /usr/local/bin/script hostname = <hostname> -p LONGLIST
. Peu importe comment j'essaie, le script ne s'exécute pas dans subprocess.Popen
L'espace avant et après "=" est obligatoire.
import subprocess
Out = subprocess.Popen(['/usr/local/bin/script', 'hostname = ', 'actual server name', '-p', 'LONGLIST'],Shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
Ce qui précède ne fonctionne pas.
Et quand j'utilise Shell = False, je reçois OSError: [Errno 8] Exec format error
OSError: [Errno 8] Exec format error
peut arriver s'il n'y a pas de ligne Shebang en haut du script Shell et si vous essayez d'exécuter le script directement. Voici un exemple qui reproduit le problème:
>>> with open('a','w') as f: f.write('exit 0') # create the script
...
>>> import os
>>> os.chmod('a', 0b111101101) # rwxr-xr-x make it executable
>>> os.execl('./a', './a') # execute it
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/os.py", line 312, in execl
execv(file, args)
OSError: [Errno 8] Exec format error
Pour résoudre ce problème, ajoutez simplement Shebang, par exemple, s’il s’agit d’un script Shell; insérez #!/bin/sh
en haut de votre script:
>>> with open('a','w') as f: f.write('#!/bin/sh\nexit 0')
...
>>> os.execl('./a', './a')
Il exécute exit 0
sans aucune erreur.
Sur les systèmes POSIX, Shell analyse la ligne de commande, c’est-à-dire que votre script ne verra aucun espace autour de =
, par exemple si script
est:
#!/usr/bin/env python
import sys
print(sys.argv)
puis l'exécuter dans le shell:
$ /usr/local/bin/script hostname = '<hostname>' -p LONGLIST
produit:
['/usr/local/bin/script', 'hostname', '=', '<hostname>', '-p', 'LONGLIST']
Remarque: pas d'espace autour de '='
. J'ai ajouté des guillemets autour de <hostname>
pour échapper aux métacaractères de redirection <>
.
Pour émuler la commande Shell en Python, exécutez:
from subprocess import check_call
cmd = ['/usr/local/bin/script', 'hostname', '=', '<hostname>', '-p', 'LONGLIST']
check_call(cmd)
Remarque: non Shell=True
. Et vous n'avez pas besoin d'échapper à <>
car aucun shell n'est exécuté.
"Exec format error"
peut indiquer que votre script
a un format invalide, exécutez:
$ file /usr/local/bin/script
pour savoir ce que c'est. Comparez l'architecture avec la sortie de:
$ uname -m
Avez-vous essayé cela?
Out = subprocess.Popen('/usr/local/bin/script hostname = actual_server_name -p LONGLIST'.split(), Shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
Edité par le commentaire d'apt de @ J.F.Sebastian
Je vais détourner ce fil pour signaler que cette erreur peut également se produire lorsque la cible de Popen n'est pas exécutable. Je l'ai appris de manière difficile quand, par accident, j'ai remplacé un fichier binaire parfaitement exécutable par un fichier Zip.
Si vous pensez que l'espace avant et après "=" est obligatoire, essayez-le séparément dans la liste.
Out = subprocess.Popen(['/usr/local/bin/script', 'hostname', '=', 'actual server name', '-p', 'LONGLIST'],Shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
Il ne serait pas faux de mentionner que Pexpect
jette une erreur similaire
#python -c "import pexpect; p=pexpect.spawn('/usr/local/ssl/bin/openssl_1.1.0f version'); p.interact()"
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/usr/lib/python2.7/site-packages/pexpect.py", line 430, in __init__
self._spawn (command, args)
File "/usr/lib/python2.7/site-packages/pexpect.py", line 560, in _spawn
os.execv(self.command, self.args)
OSError: [Errno 8] Exec format error
Ici, le fichier openssl_1.1.0f
situé dans le chemin spécifié contient la commande exec
qui y est spécifiée et exécute le fichier binaire openssl lorsqu'il est appelé.
D'habitude, je ne le mentionne pas à moins d'en avoir la cause fondamentale, mais ce problème n'existait pas auparavant. Impossible de trouver le même problème, l’explication la plus proche pour le faire fonctionner est la même que celle fournie par @jfs ci-dessus.
ce qui a fonctionné pour moi, c'est les deux
/bin/bash
au début de la commande ou du fichier que vous êtes#!/bin/sh
en première ligne.par ex.
#python -c "import pexpect; p=pexpect.spawn('/bin/bash /usr/local/ssl/bin/openssl_1.1.0f version'); p.interact()"
OpenSSL 1.1.0f 25 May 2017