以下(sh
存在する/bin/dash
)を検討してください。
$ strace -e trace=process sh -c 'grep "^Pid:" /proc/self/status /proc/$$/status'
execve("/bin/sh", ["sh", "-c", "grep \"^Pid:\" /proc/self/status /"...], [/* 47 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7fcc8b661540) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fcc8b661810) = 24865
wait4(-1, /proc/self/status:Pid: 24865
/proc/24864/status:Pid: 24864
[{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 24865
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=24865, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
exit_group(0) = ?
+++ exited with 0 +++
珍しい点はありません。grep
フォークされたプロセス(ここで行われます)はメインシェルプロセスで置き換えられます。clone()
今まではそんなに良くなった。
ここでbash 4.4を使用します。
$ strace -e trace=process bash -c 'grep "^Pid:" /proc/self/status /proc/$$/status'
execve("/bin/bash", ["bash", "-c", "grep \"^Pid:\" /proc/self/status /"...], [/* 47 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7f8416b88740) = 0
execve("/bin/grep", ["grep", "^Pid:", "/proc/self/status", "/proc/25798/status"], [/* 47 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7f8113358b80) = 0
/proc/self/status:Pid: 25798
/proc/25798/status:Pid: 25798
exit_group(0) = ?
+++ exited with 0 +++
ここで明らかなのは、grep
シェルプロセスのpidを仮定し、明示的な呼び出しfork()
はないということですclone()
。もしそうなら、問題はどのようにbash
電話なしでそのような曲芸を達成できるかということです。
ただし、clone()
コマンドにシェルリダイレクトが含まれていると、システムコールが発生します。df > /dev/null
ベストアンサー1
sh -c 'command line'
一般的にsystem("command line")
、、、、ssh host 'command line'
およびvi
より!
一般的にコマンドラインを解釈するために使用されるすべての項目に使用されるため、cron
できるだけ効率的にすることが重要です。
フォークはCPU時間、メモリ、割り当てられたファイル記述子の面で高価です。あるシェルプロセスが終了する前に別のプロセスを待つのは、リソースの無駄です。また、コマンドを実行する個々のプロセスの終了ステータス(プロセスが終了した場合など)を正しく報告することも困難になります。
多くのシェルは、最適化のためにフォークの数を最小化しようとします。最適化されていないシェルでもbash
orケースでこれを行うのが好きです。 ksh や zsh とは異なり、これはこれを行いません (サブシェルでも同じ)。 ksh93は最もフォークに強いシェルです。sh -c cmd
(cmd in subshell)
bash -c 'cmd > redir'
bash -c 'cmd1; cmd2'
次の場合は最適化できません。
sh < file
sh
そのコマンドの実行中にスクリプトにテキストを追加できるため、最後のコマンドのブランチをスキップする方法はありません。検索できないファイルの場合、ファイルの終わりを検出できません。これは、ファイル内の内容があまりにも早すぎることを意味する可能性があるためです。
または:
sh -c 'trap "echo Ouch" INT; cmd'
「最後」コマンドを実行した後、シェルは追加のコマンドを実行する必要があります。