Ошибка OSE: [Errno 8] Ошибка формата Exec

Мне трудно разобрать аргументы для подпроцесса. Открыть. Я пытаюсь выполнить скрипт на моем Unix-сервере. Синтаксис скрипта при запуске в командной строке выглядит следующим образом:/usr/local/bin/script hostname = <hostname> -p LONGLIST, Независимо от того, как я пытаюсь, скрипт не работает внутри подпроцесса. Открыть

Пробел до и после "=" является обязательным.

import subprocess
Out = subprocess.Popen(['/usr/local/bin/script', 'hostname = ', 'actual server name', '-p', 'LONGLIST'],shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)

Выше не работает.

И когда я использую shell=False, я получаю OSError: [Errno 8] Exec format error

4 ответа

OSError: [Errno 8] Exec format error Это может произойти, если в верхней части сценария оболочки нет строки Шебанга, и вы пытаетесь выполнить сценарий напрямую. Вот пример, который воспроизводит проблему:

>>> 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

Чтобы это исправить, просто добавьте шебанг, например, если это скрипт оболочки; перед именем #!/bin/sh в верхней части вашего сценария:

>>> with open('a','w') as f: f.write('#!/bin/sh\nexit 0')
... 
>>> os.execl('./a', './a')

Выполняет exit 0 без каких-либо ошибок.


В системах POSIX оболочка анализирует командную строку, т. Е. Ваш скрипт не будет видеть пробелы вокруг = например, если script является:

#!/usr/bin/env python
import sys
print(sys.argv)

затем запустить его в оболочке:

$ /usr/local/bin/script hostname = '<hostname>' -p LONGLIST

производит:

['/usr/local/bin/script', 'hostname', '=', '<hostname>', '-p', 'LONGLIST']

Примечание: вокруг нет пробелов '=', Я добавил цитаты вокруг <hostname> избежать метасимволов перенаправления <>,

Чтобы эмулировать команду оболочки в Python, выполните:

from subprocess import check_call

cmd = ['/usr/local/bin/script', 'hostname', '=', '<hostname>', '-p', 'LONGLIST']
check_call(cmd)

Примечание: нет shell=True, И вам не нужно убегать <> потому что ни одна оболочка не запускается.

"Exec format error" может означать, что ваш script имеет неверный формат, запустите:

$ file /usr/local/bin/script

чтобы узнать, что это такое. Сравните архитектуру с выводом:

$ uname -m

Я перехватываю этот поток, чтобы указать, что эта ошибка также может произойти, когда цель Popen не исполняется. Трудно научился, когда случайно переопределил отлично исполняемый двоичный файл с zip-файлом.

Вы пробовали это?

Out = subprocess.Popen('/usr/local/bin/script hostname = actual_server_name -p LONGLIST'.split(), shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE) 

Отредактировано согласно меткому комментарию от @JFSebastian

Было бы неправильно упомянуть, что Pexpect выдает похожую ошибку

#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

Здесь, openssl_1.1.0f файл по указанному пути имеет exec указанная в нем команда и запускает реальный двоичный файл openssl при вызове.

Обычно я бы не упомянул об этом, если бы у меня не было основной причины, но этой проблемы раньше не было. Невозможно найти подобную проблему, самое близкое объяснение, чтобы заставить это работать, является тем же самым как предоставленное @jfs выше.

то, что сработало для меня,

  • добавление /bin/bash в начале команды или файла вы
    столкнувшись с проблемой, или
  • добавив шебанг #!/bin/sh как первая строка.

например

#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

Если вы считаете, что пробел до и после "=" является обязательным, попробуйте использовать его как отдельный элемент в списке.

Out = subprocess.Popen(['/usr/local/bin/script', 'hostname', '=', 'actual server name', '-p', 'LONGLIST'],shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
Другие вопросы по тегам