Как понять вывод трассировки, выполняющий внешнюю команду в bash?

В Ubuntu я запускаю date непосредственно в интерактивной оболочке bash, pid которой – 6913.

 $ date Wed Mar 2 23:57:44 EST 2016 

В то же время я трассирую оболочку bash 6913 из другой интерактивной оболочки bash, используя strace :

  $ sudo strace -f -e trace=process -p 6913 Process 6913 attached clone(Process 9098 attached child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f457c05ca10) = 9098 [pid 6913] wait4(-1, <unfinished ...> [pid 9098] execve("/bin/date", ["date"], [/* 66 vars */]) = 0 [pid 9098] arch_prctl(ARCH_SET_FS, 0x7f40d6a4f740) = 0 [pid 9098] exit_group(0) = ? [pid 9098] +++ exited with 0 +++ <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WSTOPPED|WCONTINUED, NULL) = 9098 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=9098, si_status=0, si_utime=0, si_stime=0} --- wait4(-1, 0x7ffea6781518, WNOHANG|WSTOPPED|WCONTINUED, NULL) = -1 ECHILD (No child processes) clone(Process 9099 attached child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f457c05ca10) = 9099 [pid 9099] clone(Process 9100 attached child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f457c05ca10) = 9100 [pid 9099] wait4(-1, <unfinished ...> [pid 9100] execve("/bin/sed", ["sed", "s:\\([^/]\\)[^/]*/:\\1/:g"], [/* 66 vars */]) = 0 [pid 9100] arch_prctl(ARCH_SET_FS, 0x7f998bb03840) = 0 [pid 9100] exit_group(0) = ? [pid 9100] +++ exited with 0 +++ [pid 9099] <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 9100 [pid 9099] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=9100, si_status=0, si_utime=0, si_stime=0} --- [pid 9099] wait4(-1, 0x7ffea6780c58, WNOHANG, NULL) = -1 ECHILD (No child processes) [pid 9099] exit_group(0) = ? [pid 9099] +++ exited with 0 +++ --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=9099, si_status=0, si_utime=0, si_stime=0} --- wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG|WSTOPPED|WCONTINUED, NULL) = 9099 wait4(-1, 0x7ffea6780f18, WNOHANG|WSTOPPED|WCONTINUED, NULL) = -1 ECHILD (No child processes) 

Мне кажется, выход можно разделить на две части:

  1. Сначала сам bash shell 6913 clone() создает подпроцесс 9098, а затем подпроцесс 9098 выполняет execve() date и завершает.

  2. После этого сама оболочка 6913 оболочки bash создает подпроцесс 9099, а сам подпроцесс 9099 clone() сам создает подпроцесс 9100, а затем подпроцесс 9100 execve() sed . Мой вопрос касается этой второй части:

    • Должны ли последние два clone() и последний execve() принадлежать к действию, которое обрабатывает SIGCHLD, полученное оболочкой 6913 bash? Что делает действие?

    • Почему процесс 9100 execve() sed ? Что делает sed здесь?

    • Почему процесс 9099 не обрабатывает процесс execve() sed ? Почему 9099 clone() создает 9100, а затем 9100 execve() sed ? Другими словами, зачем нам нужны два последовательных клона 9099 и 9100, а не только один клон 9099?


Чтобы ответить на комментарий:

 $ echo $PROMPT_COMMAND pwd2=$(sed "s:\([^/]\)[^/]*/:\1/:g" <<<$PWD) $ echo $PS1 \u@\h:$pwd2\$ 

После unset PROMPT_COMMAND в unset PROMPT_COMMAND 6913 unset PROMPT_COMMAND , вывод трассировки

 $ sudo strace -f -e trace=process -p 6913 [sudo] password for t: Process 6913 attached clone(Process 12918 attached child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f457c05ca10) = 12918 [pid 6913] wait4(-1, <unfinished ...> [pid 12918] execve("/bin/date", ["date"], [/* 66 vars */]) = 0 [pid 12918] arch_prctl(ARCH_SET_FS, 0x7ff00c632740) = 0 [pid 12918] exit_group(0) = ? [pid 12918] +++ exited with 0 +++ <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WSTOPPED|WCONTINUED, NULL) = 12918 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12918, si_status=0, si_utime=0, si_stime=0} --- wait4(-1, 0x7ffea6781518, WNOHANG|WSTOPPED|WCONTINUED, NULL) = -1 ECHILD (No child processes) 

Итак, первые два вышеперечисленных вопроса теперь отвечают. Я до сих пор не уверен в третьем вопросе.

One Solution collect form web for “Как понять вывод трассировки, выполняющий внешнюю команду в bash?”

 clone(Process 9099 attached child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f457c05ca10) = 9099 [pid 9099] clone(Process 9100 attached child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f457c05ca10) = 9100 [pid 9099] wait4(-1, <unfinished ...> [pid 9100] execve("/bin/sed", ["sed", "s:\\([^/]\\)[^/]*/:\\1/:g"], [/* 66 vars */]) = 0 

Две вилки (на современных системах Linux, вилки выполняются с использованием системного вызова clone ) связаны с оценкой bash вашей переменной PROMPT_COMMAND , которую вы сказали

 pwd2=$(sed "s:\([^/]\)[^/]*/:\1/:g" <<<$PWD) 

Вилки напрямую не связаны с ранее полученным сигналом SIGCHLD.

В руководстве bash говорится:

Значение переменной PROMPT_COMMAND проверяется непосредственно перед тем, как Bash распечатает каждое основное приглашение. Если PROMPT_COMMAND установлен и имеет ненулевое значение, то значение выполняется так же, как если бы оно было введено в командной строке.

Внутри bash в конечном итоге вызывает parse_and_execute для оценки содержимого PROMPT_COMMAND . Бэш пытается минимизировать количество вилок, которые ему нужно сделать. Для простых операторов, таких как pwd2=$PWD , не нужны вилки. Для более сложных операторов может быть сделана одна или несколько вилок. В вашем случае $( ... ) приводит к fork, pid 9099, оболочки, которая затем оценивает команду между круглыми скобками. Вызов не встроенной утилиты sed приводит к другой вилке, pid 9100, за которой следует execve /bin/sed .

Что делает sed здесь?

Кажется, он отрубает все, кроме первого символа имени каждого каталога над текущим рабочим каталогом.

  • Как определить определенный системный вызов, вызванный или нет, во всем рабочем процессе?
  • Пример нескольких строк из распечатки strace
  • Самый изящный способ прекратить навязчивую программу
  • Как «раскодировать» сокет домена unix?
  • Отслеживание процесса узла, выполняющего мой скрипт с «npm start»
  • Измерять задержки ввода-вывода на диске для выполняемого процесса
  • Не удается поймать создание файла с помощью strace
  • Почему «w» здесь требует больше системных вызовов, чем простой скрипт python?
  • Выход Strace не отображает системный вызов
  • Использование strace для файла C
  • Почему Firefox застрял, и как я могу его отклеить?
  • Linux и Unix - лучшая ОС в мире.