Как выполнить команду оболочки, получить вывод и pwd после команды в Python

Как я могу выполнить команду оболочки, может быть сложной, как обычная команда в командной строке bash, получить вывод этой команды и pwd после выполнения?

Я использовал такую ​​функцию:

import subprocess as sub

def execv(command, path):
    p = sub.Popen(['/bin/bash', '-c', command],
                    stdout=sub.PIPE, stderr=sub.STDOUT, cwd=path)
    return p.stdout.read()[:-1]

И я проверяю, использует ли пользователь команду cd, но это не сработает, когда пользователь использует символическую ссылку на компакт-диск или другой странный способ изменить каталог.

и мне нужен словарь, который содержит {'cwd': '<NEW PATH>', 'result': '<COMMAND OUTPUT>'}


person jcubic    schedule 15.06.2012    source источник


Ответы (3)


Если вы используете subprocess.Popen, вы должны получить объект канала, который вы можете communicate() использовать для вывода команды и использовать .pid() для получения идентификатора процесса. Я был бы действительно удивлен, если бы вы не смогли найти способ получить текущий рабочий каталог процесса по pid...

например: http://www.cyberciti.biz/tips/linux-report-current-working-directory-of-process.html

person Daren Thomas    schedule 15.06.2012
comment
Я пробую это, есть каталог /proc/‹PID›/cwd, который код должен проверить, он может сделать это, используя ls или file (и результат синтаксического анализа), но когда код выполняет эти команды, cwd больше не читается, потому что процесс завершен. Поэтому вам нужно добавить команду сна после выполненной команды. Лучше просто запустить pwd. - person jcubic; 25.07.2013

Чтобы получить вывод произвольной команды оболочки с ее окончательным cwd (при условии, что в cwd нет новой строки):

from subprocess import check_output

def command_output_and_cwd(command, path):
    lines = check_output(command + "; pwd", shell=True, cwd=path).splitlines()
    return dict(cwd=lines[-1], stdout=b"\n".join(lines[:-1]))
person jfs    schedule 25.07.2013

Я перенаправляю stdout на stderr команды pwd. если stdout пуст и stderr не является путем, то stderr является ошибкой команды

import subprocess as sub

def execv(command, path):
    command = 'cd %s && %s && pwd 1>&2' % (path, command)
    proc = sub.Popen(['/bin/bash', '-c', command],
                     stdout=sub.PIPE, stderr=sub.PIPE)
    stderr = proc.stderr.read()[:-1]
    stdout = proc.stdout.read()[:-1]
    if stdout == '' and not os.path.exists(stderr):
        raise Exception(stderr)
    return {
        "cwd": stderr,
        "stdout": stdout
    }

ОБНОВЛЕНИЕ: вот лучшая реализация (используя последнюю строку для pwd и не используя stderr)

def execv(command, path):
    command = 'cd %s && %s 2>&1;pwd' % (path, command)
    proc = sub.Popen(['/bin/bash', '-c', command],
                     env={'TERM':'linux'},
                     stdout=sub.PIPE)
    stdout = proc.stdout.read()
    if len(stdout) > 1 and stdout[-1] == '\n':
        stdout = stdout[:-1]
    lines = stdout.split('\n')
    cwd = lines[-1]
    stdout = '\n'.join(lines[:-1])
    return {
        "cwd": cwd,
        "stdout": man_to_ansi(stdout)
    }
person jcubic    schedule 15.06.2012