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.