Qual é a diferença de executar um comando diretamente em um shell bash e executá-lo como bash -c <command>
em um shell bash?
O objetivo da minha pergunta é que eu gostaria de saber como um comando é executado com e sem bash -c
no shell. Essas informações são parte do que pode me ajudar a pensar sobre minhas perguntas anteriores link e Por que as variáveis não-ambientais são passadas para a subshell que é invocada pela substituição de comandos?
A seguir, uma maneira de tentar entender a pergunta acima via strace
. Mas você pode explicar a diferença sem usar strace
.
Eu considero dois casos, executando bash -c date
e executando bash -c 'date&'
.
Quando executo bash -c date
no bash shell com pid 6913 e rastreio
shell em outro shell:
$ sudo strace -f -e trace=process -p 6913
Process 6913 attached
clone(Process 13010 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,child_tidptr=0x7f457c05ca10) = 13010
[pid 6913] wait4(-1, <unfinished ...>
[pid 13010] execve("/bin/bash", ["bash", "-c", "date"], [/* 66 vars */]) = 0
[pid 13010] arch_prctl(ARCH_SET_FS, 0x7f920c591740) = 0
[pid 13010] execve("/bin/date", ["date"], [/* 66 vars */]) = 0
[pid 13010] arch_prctl(ARCH_SET_FS, 0x7f67e34df740) = 0
[pid 13010] exit_group(0) = ?
[pid 13010] +++ exited with 0 +++
<... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WSTOPPED|WCONTINUED, NULL) = 13010
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=13010, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, 0x7ffea6781518, WNOHANG|WSTOPPED|WCONTINUED, NULL) = -1 ECHILD (No child processes)
Em comparação com a execução de date
no bash shell (veja abaixo), é o
diferença só que aqui temos mais uma linha entre o primeiro
clone()
e execve()
date
:
execve("/bin/bash", ["bash", "-c", "date"], [/* 66 vars */]) = 0
O que a diferença significa?
Rastreando a saída da execução de date
em vez de bash -c date
:
$ 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)
Quando executo bash -c 'date&'
no shell bash com pid 6913 e rastreio
o shell em outro shell:
$ sudo strace -f -e trace=process -p 6913
Process 6913 attached
clone(Process 13023 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,child_tidptr=0x7f457c05ca10) = 13023
[pid 6913] wait4(-1, <unfinished ...>
[pid 13023] execve("/bin/bash", ["bash", "-c", "date&"], [/* 66 vars */]) = 0
[pid 13023] arch_prctl(ARCH_SET_FS, 0x7f154970b740) = 0
[pid 13023] clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,child_tidptr=0x7f154970ba10) = 13024
[pid 13023] exit_group(0) = ?
[pid 13023] +++ exited with 0 +++
<... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WSTOPPED|WCONTINUED, NULL) = 13023
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=13023, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, 0x7ffea6781518, WNOHANG|WSTOPPED|WCONTINUED, NULL) = -1 ECHILD (No child processes)
Process 13024 attached
[pid 13024] execve("/bin/date", ["date"], [/* 66 vars */]) = 0
[pid 13024] arch_prctl(ARCH_SET_FS, 0x7f8045f35740) = 0
[pid 13024] exit_group(0) = ?
[pid 13024] +++ exited with 0 +++
Em comparação com a execução de date&
no bash shell (veja abaixo), o
diferença parece não ter apenas um execve
extra:
execve("/bin/bash", ["bash", "-c", "date&"], [/* 66 vars */]) = 0
mas também o arranjo de criação de subprocessos, cujo subprocesso
execve()
date
e qual subprocesso execve()
/bin/bash
.
O que a diferença significa?
Rastreando a saída ao executar date&
em vez de bash -c 'date&'
:
$ sudo strace -f -e trace=process -p 6913
Process 6913 attached
clone(Process 12931 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,child_tidptr=0x7f457c05ca10) = 12931
[pid 12931] execve("/bin/date", ["date"], [/* 66 vars */]) = 0
[pid 12931] arch_prctl(ARCH_SET_FS, 0x7f530c5ee740) = 0
[pid 12931] exit_group(0) = ?
[pid 12931] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12931, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG|WSTOPPED|WCONTINUED, NULL) = 12931
wait4(-1, 0x7ffea6780718, WNOHANG|WSTOPPED|WCONTINUED, NULL) = -1 ECHILD (No child processes)