Короче говоря: я хотел бы отследить способ вызова некоторых исполняемых файлов для отслеживания поведения системы. Допустим, у меня есть исполняемый файл:
/usr/bin/do_stuff
И он на самом деле вызывается несколькими разными именами через символическую ссылку:
/usr/bin/make_tea -> /usr/bin/do_stuff
/usr/bin/make_coffee -> /usr/bin/do_stuff
и так далее. Очевидно, do_stuff
что будет использоваться первый полученный аргумент, чтобы определить, какое действие на самом деле предпринимается, а остальные аргументы будут обработаны в свете этого.
Я хотел бы записать когда-либо вызов /usr/bin/do_stuff
(и полный список аргументов). Если бы не было символических ссылок, я просто перешел do_stuff
бы do_stuff_real
и написал скрипт
#!/bin/sh
echo "$0 $@" >> logfile
/usr/bin/do_stuff_real "$@"
Однако, поскольку я знаю, что он будет проверять имя, по которому он называется, это не сработает. Как написать сценарий для достижения того же самого, но при этом передать do_stuff
правильное «исполняемое имя»?
Для записи, чтобы избежать ответов на эти строки:
- Я знаю, что могу сделать это в C (используя execve), но было бы намного проще, если бы я мог, в этом случае, просто использовать скрипт оболочки.
- Я не могу просто заменить
do_stuff
программой регистрации.
источник
sh
, вы можете использоватьmybase=${0##*/}
вместо basename.basename
вызовbasename -- foo.bar
мне незнаком, и в системе Linux, на которой я его тестировал, получается результат,foo.bar
который может нарушить работу сценария. Вы уверены, что это распространенный метод?basename -- foo.bar
возвращаетсяfoo.bar
,basename -- --foo--/bar
возвращается,bar
как ожидалось.basename "$foo"
работает, только если вы можете гарантировать$foo
, не начинается с-
. Общий синтаксис для вызова команды с произвольными параметрами являетсяcmd -x -y -- "$argument"
.cmd "$argument"
это неправильно, если вы не имеете в видуcmd "$option_or_arg"
. Теперь некоторые команды (включая некоторые исторические реализацииbasename
) не поддерживают,--
поэтому вам иногда приходится выбирать между переносимостью и надежностью.Вы можете использовать
exec -a
(как найти вbash
,ksh93
,zsh
,mksh
,yash
но не POSIX пока) , который используется для указанияargv[0]
на исполнение команды:Обратите внимание, что
$0
это не то,argv[0]
что получает команда. Это путь к скрипту, который передаетсяexecve()
(и который передается в качестве аргументаbash
), но этого вполне достаточно для вашей цели.Как пример, если
make_tea
был вызван как:Как обычно делает оболочка при вызове команды по имени (поиск исполняемого файла в
$PATH
), оболочка должна:Это не:
но это достаточно хорошо, так как
do_stuff_real
знает, что это значит сделать чай.Где это было бы проблемой, если
do_stuff
был вызван как:как это будет переведено на:
Это не произойдет во время обычных операций, но обратите внимание, что наша оболочка делает что-то подобное.
В большинстве систем ,
argv[0]
как передается сценарий потерян после того , как интерпретатор (здесь/bin/bash
) выполняется ( интерпретатора на большинстве систем это путь дается на нее-бэнг линии ) , так что нет ничего, что сценарий оболочки может сделать.argv[0]
Если вы хотите передать его
argv[0]
, вам нужно скомпилировать исполняемый файл. Что-то вроде:источник
perl
или,python
если доступно. Старые версииzsh
не поддерживалиexec -a
, но вы всегда можете использоватьARGV0=the-argv-0 cmd args
вместо этого.zsh
(хотя теперь вы дали понять, что вы этого не сделали), но он был слишком стар, вы все равно могли бы использовать егоARGV0
там.