Как изменить argv0 в bash, чтобы команда отображалась с другим именем в ps? - PullRequest
22 голосов
/ 15 июля 2010

В программе на C я могу написать argv [0], и новое имя появится в списке ps.

Как я могу сделать это в bash?

Ответы [ 7 ]

26 голосов
/ 15 июля 2010

Вы можете сделать это при запуске новой программы через exec -a <newname>.

9 голосов
/ 19 ноября 2014

Просто для протокола, хотя он не совсем отвечает на вопрос оригинального автора, это что-то тривиальное с zsh:

ARGV0=emacs nethack
9 голосов
/ 20 июля 2010

У меня была возможность просмотреть исходный код для bash, и похоже, что нет никакой поддержки записи в argv [0].

6 голосов
/ 28 апреля 2014

Я предполагаю, что у вас есть сценарий оболочки, который вы хотите выполнить так, чтобы сам процесс сценария получил новый argv[0]. Например (я только что проверил это в bash, поэтому я использую это, но это может работать в другом месте).

#!/bin/bash

echo "process $$ here, first arg was $1"
ps -p $$

Вывод будет примерно таким:

$ ./script arg1
process 70637 here, first arg was arg1
  PID TTY           TIME CMD
70637 ttys003    0:00.00 /bin/bash ./script arg1

Итак, ps показывает оболочку, /bin/bash в данном случае. Теперь попробуйте интерактивную оболочку exec -a, но в подоболочке, чтобы не сдуть интерактивную оболочку:

$ (exec -a MyScript ./script arg1)
process 70936 here, first arg was arg1
  PID TTY           TIME CMD
70936 ttys008    0:00.00 /bin/bash /path/to/script arg1

Woops, все еще показывая /bin/bash. что случилось? exec -a, вероятно, установил argv[0], но затем начался новый экземпляр bash, потому что операционная система прочитала #!/bin/bash в верхней части вашего скрипта. Хорошо, что если мы как-нибудь выполним exec'ing внутри скрипта? Во-первых, нам нужен какой-то способ определить, является ли это «первым» выполнением скрипта или вторым экземпляром exec ed, в противном случае второй экземпляр будет выполняться снова и снова и снова в бесконечном цикле. Далее нам нужен исполняемый файл, чтобы , а не был файлом со строкой #!/bin/bash вверху, чтобы ОС не смогла изменить желаемое значение argv [0]. Вот моя попытка:

$ cat ./script
#!/bin/bash

__second_instance="__second_instance_$$"
[[ -z ${!__second_instance} ]] && {
  declare -x "__second_instance_$$=true"
  exec -a MyScript "$SHELL" "$0" "$@"
}

echo "process $$ here, first arg was $1"
ps -p $$

Благодаря этому ответу я сначала проверяю переменную среды __second_instance_$$, основанную на PID (который не изменяется через exec), чтобы он не конфликтовал с другими сценариями, используя эта техника. Если он пуст, я предполагаю, что это первый экземпляр, и я экспортирую эту переменную среды, а затем exec. Но, что важно, я не исполняю этот сценарий, а исполняю двоичный файл оболочки напрямую, используя этот сценарий ($0) в качестве аргумента, передавая также все остальные аргументы ($@). Переменная окружения немного взломана.

Теперь вывод такой:

$ ./script arg1
process 71143 here, first arg was arg1
  PID TTY           TIME CMD
71143 ttys008    0:00.01 MyScript ./script arg1

Это почти там. argv[0] - это MyScript, как я хочу, но есть дополнительный аргумент ./script, который является следствием непосредственного выполнения оболочки (а не обработки #! в ОС). К сожалению, я не знаю, как лучше, чем этот.

Обновление для Bash 5.0

Похоже, в Bash 5.0 добавлена ​​поддержка записи в специальную переменную BASH_ARGV0 , поэтому это должно стать намного проще.

(см. объявление о выпуске )

6 голосов
/ 15 июля 2010
( exec -a foo bash -c 'echo $0' ) 
0 голосов
/ 02 декабря 2016

Скопируйте исполняемый файл bash под другим именем.

Вы можете сделать это в самом скрипте ...

cp /bin/bash ./new-name
PATH=$PATH:.
exec new-name $0

Если вы пытаетесь притвориться, что вы не являетесь сценарием оболочки, вы можете переименовать сам сценарий во что-нибудь классное или даже "" (один пробел), так что

exec new-name " "

Выполнит bash ваш скрипт и появится в списке ps как new-name.

ОК, поэтому вызывать скрипт "" - очень плохая идея :)

В основном, для изменения имени

bash script

переименуйте bash и переименуйте скрипт.

Если вы беспокоитесь, как мистер МакДом. очевидно, что при копировании двоичного файла под новое имя (что совершенно безопасно), вы также можете создать символическую ссылку

ln -s /bin/bash ./MyFunkyName
./MyFunkyName

Таким образом, символическая ссылка - это то, что появляется в списке ps. (снова используйте PATH = $ PATH:., если вы не хотите ./)

0 голосов
/ 15 июля 2010

Я просто добавлю, что это должно быть возможно во время выполнения, по крайней мере, в некоторых средах. Назначение $ 0 в perl на linux меняет то, что отображается в ps. Я не знаю, как это реализовано, однако. Если я смогу узнать, я обновлю это.

редактирование: Судя по тому, как это делает perl, это нетривиально. Я сомневаюсь, что во время выполнения есть какой-нибудь встроенный баск, но точно не знаю. Вы можете увидеть , как perl устанавливает имя процесса во время выполнения .

...