Python subprocess.call a bash alias

На работе есть script, в котором перечислены завершенные задачи. Это было написано кем-то еще и размещено по сети. У меня есть псевдоним в моем .bashrc, который вызывает этот script, с его множеством флагов и т.д., И я хотел написать python script, который будет вызывать этот псевдоним каждые несколько минут, чтобы я мог открыть оболочку с обновленной статистикой, Однако subprocess.call("myAlias") не выполняется. Я до сих пор довольно новичок в python, и я изо всех сил пытаюсь понять это.

from subprocess import call

def callAlias():
    call("myAlias")

callAlias()

Я планирую добавить еще слишком много, но я ударил эту ловушку на первом шаге.: P

Я бы опубликовал больше, но там много конфиденциального конфиденциального материала, с которым мне нужно быть осторожным. Извините за неопределенный код и отсутствие вывода ошибок.

Ответы

Ответ 1

Если требуемый псевдоним определен в ~/.bashrc, он не будет запускаться по нескольким причинам:

1) Вы должны указать ключевое слово "shell" arg:

subprocess.call('command', shell=True)

В противном случае ваша данная команда используется для поиска исполняемого файла, а не для передачи в оболочку, и это оболочка, которая расширяет такие вещи, как псевдонимы и функции.

2) По умолчанию subprocess.call и друзья используют оболочку '/bin/sh'. Если это псевдоним Bash, который вы хотите вызвать, вам нужно указать подпроцессу использовать Bash вместо sh, используя ключевое слово "executable" arg:

subprocess.call('command', shell=True, executable='/bin/bash')

3) Однако, /bin/ bash не будет source ~/.bashrc, если только он не запущен как "интерактивная" оболочка (с "-i".) К сожалению, вы не можете передать исполняемый файл = '/bin/bash -i ', поскольку он считает, что все значение является именем исполняемого файла. Поэтому, если ваш псевдоним определен в обычном интерактивном запуске пользователя, например. в .bashrc, тогда вам придется вызвать команду, используя эту альтернативную форму:

subprocess.call(['/bin/bash', '-i', '-c', command])
# i.e. shell=False (the default)

Ответ 2

Вам нужно установить для ключевого слова shell значение True:

call("myAlias", shell=True)

В соответствующая документация:

Если shell - True, указанная команда будет выполнена через оболочку. Это может быть полезно, если вы используете Python в первую очередь для расширенного потока управления, который он предлагает для большинства системных оболочек, и по-прежнему хотят получить доступ к другим функциям оболочки, таким как групповые символы файлов, оболочки оболочки и расширение переменной среды.

Псевдонимы - это функция оболочки (например, они определены и интерпретируются оболочкой).

Однако оболочка (/bin/sh) выполняется неинтерактивно, поэтому никакие файлы .profile или .bashrc не читаются, и ваш псевдоним, вероятно, не будет доступен.

Если вы неохотно используете полную расширенную команду в свой python script, вам нужно будет использовать переменную среды $ENV, чтобы сделать оболочку прочитайте файл с указанным в нем псевдонимом:

call("myAlias", shell=True, env=dict(ENV='/path/to/aliasfile'))

Ответ 3

Я немного изменил причину Джонатана # 2, чтобы сделать эту работу. Создайте файл /usr/local/bin/interactive_bash который содержит

#!/bin/bash
/bin/bash -i "[email protected]"

и chmod +x это. Тогда из Python вы можете позвонить

subprocess.call('my_alias', shell=True, executable='/usr/local/bin/interactive_bash')

Ответ 4

Рекомендуемое решение состоит в том, чтобы не использовать псевдоним для определения функциональности, которая не предназначена исключительно для интерактивного использования (и даже в этом случае функции оболочки превосходят ряд способов).

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

Более подробно, если у вас есть

alias myalias='for x in foo bar baz; do
    frobnicate "$x"; done'

вы можете улучшить его, чтобы он не загрязнял ваше глобальное пространство имен, превратив его в функцию

myalias () {
    local x
    for x in foo bar baz; do
        frobnicate "$x"
    done
}

или просто сохраните его как /usr/local/bin/myalias и chmod a+x/usr/local/bin/myalias чтобы сделать его исполняемым для всех;

#!/bin/sh
for x in foo bar baz; do
    frobnicate "$x"
done

(Это выполняется в подпроцессе, поэтому по окончании работы сценария x исчезнет; поэтому нам не нужно делать его local.)

(Конечно, если frobnicate написан грамотно, может быть, вы можете упростить и frobnicate foo bar baz).

Это общий FAQ.