У меня есть скрипт bash foocaller
, который вызывает скрипт ruby foo
:
фукаллер
/path/to/foo
В пределах foo
, я хочу получить путь foocaller
. Следуяэто предложение, для этого я добавил следующий код:
фу
#!/usr/bin/env ruby
puts File.read("/proc/#{Process.ppid}/cmdline")
Когда я бегу:
$ bash foocaller
то я получаю желаемое:
bash^@/path/to/foocaller
но когда я звоню напрямую foocaller
:
$ foocaller
то я получаю это:
/bin/bash^@--noediting^@-i
который не показывает путь к foocaller
. Как я могу получить путь к , foocaller
напрямую вызвав foocaller
без bash
?
решение1
Многие оболочки оптимизируют последнюю команду в скрипте, выполняя команду в том же процессе:
$ sh -c 'ps
ps'
PID TTY TIME CMD
32673 pts/3 00:00:00 zsh
32696 pts/3 00:00:00 sh
32697 pts/3 00:00:00 ps
PID TTY TIME CMD
32673 pts/3 00:00:00 zsh
32696 pts/3 00:00:00 ps
Посмотрите, как второй ps
был выполнен в процессе, который был запущен изначально sh
(32696), а затем его родительским объектом является sh
родительский объект (в моем случае это zsh
моя интерактивная оболочка).
Этого можно избежать, добавив exit
строку:
#! /bin/sh -
foo
exit
sh
не может выполняться foo
в том же процессе, потому что ему все еще есть что интерпретировать после foo
завершения. Поэтому он вместо этого запустится foo
в другом процессе и будет ждать его. А затем запустится exit
(что приведет к выходу из скрипта с тем же статусом выхода, что и у foo
).
Это не совсем оптимально, поскольку здесь можно было бы сэкономить целый процесс.
Лучший способ узнать foo
о пути — foocaller
это сообщить ему:
#! /bin/sh -
CALLER=$0 foo
Затем foo
можно запросить CALLER
переменную окружения, чтобы получить путь к вызывающей стороне ( import os;print(os.environ["CALLER"])
в Python)