Нет требования, чтобы первый из аргументов имел какое-либо отношение к имени исполняемого файла:
int main(void)
{
char *args[3] = { "rip van winkle", "30", 0 };
execv("/bin/sleep", args);
return 1;
}
Попробуйте - на Mac (после трех тестов):
make x; ./x & sleep 1; ps
Выход на третий прогон был:
MiniMac JL: make x; ./x & sleep 1; ps
make: `x' is up to date.
[3] 5557
PID TTY TIME CMD
5532 ttys000 0:00.04 -bash
5549 ttys000 0:00.00 rip van winkle 30
5553 ttys000 0:00.00 rip van winkle 30
5557 ttys000 0:00.00 rip van winkle 30
MiniMac JL:
Комментарии EBM:
Да, и это делает это еще более странным. В моем тестовом скрипте bash (цель execve) я нигде не вижу значения того, что execve имеет в arg [0] - не в среде и не как $ 0.
Пересмотр эксперимента - скрипт с именем 'bash.script':
#!/bin/bash
echo "bash script at sleep (0: $0; *: $*)"
sleep 30
И пересмотренная программа:
int main(void)
{
char *args[3] = { "rip van winkle", "30", 0 };
execv("./bash.script", args);
return 1;
}
Это дает вывод ps:
bash script at sleep (0: ./bash.script; *: 30)
PID TTY TIME CMD
7804 ttys000 0:00.11 -bash
7829 ttys000 0:00.00 /bin/bash ./bash.script 30
7832 ttys000 0:00.00 sleep 30
На мой взгляд, есть две возможности:
- Ядро выполняет жонглирование командной строки при выполнении сценария через строку shebang ('
#!/bin/bash
') или
- Сам Bash dink со своим списком аргументов.
Как установить разницу? Я полагаю, что копирование оболочки на альтернативное имя, а затем использование этого альтернативного имени в шебанге скажет нам кое-что:
$ cp /bin/bash jiminy.cricket
$ sed "s%/bin/bash%$PWD/jiminy.cricket%" bash.script > tmp
$ mv tmp bash.script
$ chmod +w bash.script
$ ./x & sleep 1; ps
[1] 7851
bash script at sleep (0: ./bash.script; *: 30)
PID TTY TIME CMD
7804 ttys000 0:00.12 -bash
7851 ttys000 0:00.01 /Users/jleffler/tmp/soq/jiminy.cricket ./bash.script 30
7854 ttys000 0:00.00 sleep 30
$
Это, я думаю, указывает на то, что ядро переписывает argv[0]
при использовании механизма Шебанга.
Обращаясь к комментарию nategoose:
MiniMac JL: pwd
/Users/jleffler/tmp/soq
MiniMac JL: cat al.c
#include <stdio.h>
int main(int argc, char **argv)
{
while (*argv)
puts(*argv++);
return 0;
}
MiniMac JL: make al.c
cc al.c -o al
MiniMac JL: ./al a b 'c d' e
./al
a
b
c d
e
MiniMac JL: cat bash.script
#!/Users/jleffler/tmp/soq/al
echo "bash script at sleep (0: $0; *: $*)"
sleep 30
MiniMac JL: ./x
/Users/jleffler/tmp/soq/al
./bash.script
30
MiniMac JL:
Это показывает, что механизм shebang '#! / Path / to / program', а не любая программа, такая как Bash, регулирует значения argv[0]
. Таким образом, когда исполняется двоичный файл, значение argv[0]
не корректируется; когда скрипт выполняется через шебанг, список аргументов корректируется ядром; argv[0]
- двоичный файл, указанный на шебанге; если после шебанга есть аргумент, он становится argv[1]
; следующий аргумент - это имя файла сценария, за которым следуют все оставшиеся аргументы из execv()
или эквивалентного вызова.
MiniMac JL: cat bash.script
#!/Users/jleffler/tmp/soq/al -arg0
#!/bin/bash
#!/Users/jleffler/tmp/soq/jiminy.cricket
echo "bash script at sleep (0: $0; *: $*)"
sleep 30
MiniMac JL: ./x
/Users/jleffler/tmp/soq/al
-arg0
./bash.script
30
MiniMac JL: