What is the difference of running a command directly in a bash shell, and run it as bash -c <command>
in a bash shell?
The purpose of my question is that I would like to know how a command is executed with and without bash -c
in shell. Such information is part of what can help me think about my previous questions https://unix.stackexchange.com/questions/261595/do-a-bash-script-and-bash-c-command-run-in-a-subshell-environment, and Why are non-environment variables passed to the subshell invoqued by command substitution?
The following is a way that I try to understand the above question via strace
. But you can explain the difference without using strace
.
I consider two cases, running bash -c date
and running bash -c 'date&'
.
When I run
bash -c date
in bash shell with pid 6913, and trace the shell in another 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)
Compared to running
date
in bash shell (see below), is the difference only that here we have one more line between the firstclone()
and theexecve()
date
:execve("/bin/bash", ["bash", "-c", "date"], [/* 66 vars */]) = 0
What does the difference mean?
Tracing output of running
date
instead ofbash -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)
When I run
bash -c 'date&'
in bash shell with pid 6913, and trace the shell in another 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 +++
Compared to running
date&
in bash shell (see below), the difference seems not just having one extraexecve
:execve("/bin/bash", ["bash", "-c", "date&"], [/* 66 vars */]) = 0
but also arrangement of creation of subprocesses, which subprocess
execve()
date
and which subprocessexecve()
/bin/bash
.What does the difference mean?
Tracing output when running
date&
instead ofbash -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)
bash -c
in shell. Part of the Information that can help to answer my previous questions http://unix.stackexchange.com/questions/261595/do-a-bash-script-and-bash-c-command-run-in-a-subshell-environment, and http://unix.stackexchange.com/questions/261402/why-are-non-environment-variables-passed-to-the-subshell-invoqued-by-command-sub – Tim Mar 03 '16 at 18:41But really, that's it. Bash->date or bash->bash->date.
– Hack Saw Mar 17 '16 at 22:25