Здесь проблема: у меня есть этот скрипт foo.py
, и если пользователь вызывает его без опции --bar
, я бы хотел отобразить следующее сообщение об ошибке:
Please add the --bar option to your command, like so:
python foo.py --bar
Теперь сложная часть состоит в том, что пользователь может вызвать несколько способов:
- Возможно, они использовали
python foo.py
как в примере - Возможно, они использовали
/usr/bin/foo.py
- У них может быть псевдоним оболочки
frob='python foo.py'
, и на самом деле он запускалfrob
- Возможно, это даже git alias
flab=!/usr/bin/foo.py
, и они использовалиgit flab
В каждом случае я хотел бы, чтобы сообщение отражало, как пользователь вызывается этой командой, так что пример, который я предоставляю, имеет смысл.
sys.argv
всегда содержит foo.py
, а /proc/$$/cmdline
не знает о псевдонимах. Мне кажется, что единственным возможным источником этой информации будет сам bash, но я не знаю, как его спросить.
Есть идеи?
ОБНОВЛЕНИЕ Как насчет того, ограничиваем ли мы возможные сценарии только перечисленными выше?
ОБНОВЛЕНИЕ 2: Множество людей написало очень хорошее объяснение, почему это невозможно в общем случае, поэтому я хотел бы ограничить свой вопрос:
При следующих предположениях:
- Сценарий запускался интерактивно, начиная с bash
- Сценарий запускался одним из следующих трех способов:
-
foo <args>
где foo - символическая ссылка /usr/bin/foo → foo.py -
git foo
где alias.foo =!/usr/bin/foo in~/.gitconfig
-
git baz
где alias.baz =!/usr/bin/foo in~/.gitconfig
-
Есть ли способ отличить 1 и (2,3) от сценария? Есть ли способ различать 2 и 3 из сценария?
Я знаю, что это длинный выстрел, поэтому я сейчас принимаю ответ Чарльза Даффи.
ОБНОВЛЕНИЕ 3: До сих пор наиболее перспективный угол был предложен Чарльзом Даффи в комментариях ниже. Если я могу заставить своих пользователей иметь
trap 'export LAST_BASH_COMMAND=$(history 1)' DEBUG
в их .bashrc
, то я могу использовать что-то вроде этого в моем коде:
like_so = None
cmd = os.environ['LAST_BASH_COMMAND']
if cmd is not None:
cmd = cmd[8:] # Remove the history counter
if cmd.startswith("foo "):
like_so = "foo --bar " + cmd[4:]
elif cmd.startswith(r"git foo "):
like_so = "git foo --bar " + cmd[8:]
elif cmd.startswith(r"git baz "):
like_so = "git baz --bar " + cmd[8:]
if like_so is not None:
print("Please add the --bar option to your command, like so:")
print(" " + like_so)
else:
print("Please add the --bar option to your command.")
Таким образом, я показываю общее сообщение, если мне не удается получить их метод вызова. Конечно, если я буду полагаться на изменение среды моих пользователей, я мог бы также гарантировать, что различные псевдонимы будут экспортировать собственные переменные среды, на которые я могу смотреть, но по крайней мере этот способ позволяет мне использовать ту же технику для любых другой скрипт, который я могу добавить позже.