1

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&'.

  1. 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 datein bash shell (see below), is the difference only that here we have one more line between the first clone() and the execve() date:

    execve("/bin/bash", ["bash", "-c", "date"], [/* 66 vars */]) = 0
    

    What does the difference mean?

    Tracing output of running date instead of 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)
    
  2. 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 extra execve:

    execve("/bin/bash", ["bash", "-c", "date&"], [/* 66 vars */]) = 0
    

    but also arrangement of creation of subprocesses, which subprocess execve() date and which subprocess execve() /bin/bash.

    What does the difference mean?

    Tracing output when running date& instead of 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)
    
Tim
  • 101,790
  • You seem to know a heckuva lot about the system, so I'm not sure where you are coming from with the question. The answer on the face of it is that 'bash -c date' is asking a new instance of bash to run date, whereas 'date' alone runs it without the extra shell. – Hack Saw Mar 03 '16 at 18:34
  • Are you asking what the advantage is of either approach? – Hack Saw Mar 03 '16 at 18:35
  • I am asking how a command is executed with and without 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:41
  • The clone lines are where the action is. There is an untraced clone wherein the subshell execve's data.

    But really, that's it. Bash->date or bash->bash->date.

    – Hack Saw Mar 17 '16 at 22:25

0 Answers0