Jika Anda menjalankan ini di bawah strace, Anda dapat melihat bahwa versi yang menggunakan ls
memulai perintah dalam sebuah subkulit, di mana versi yang menggunakan gema mengeksekusi semuanya dalam shell yang ada.
Bandingkan keluaran dari
$ strace -f /bin/bash -o trace.txt -c 'i=5; echo $i; echo file_c-$((++i)).txt; echo $i'
5
6
6
melawan
strace -f /bin/bash -o trace.txt -c 'i=5; echo $i; ls > file_c-$((++i)).txt; echo $i'
5
5
Anda akan melihat yang pertama:
1251 execve("/bin/bash", ["/bin/bash", "-c", "i=5; echo $i; echo file_c-$(( ++"...], [/* 19 vars */]) = 0
...
1251 write(1, "5\n", 2) = 2
1251 write(1, "file_c-6.txt\n", 13) = 13
1251 write(1, "6\n", 2) = 2
Dan yang kedua:
1258 execve("/bin/bash", ["/bin/bash", "-c", "i=5; echo $i; ls > file_c-$(( ++"...], [/* 19 vars */]) = 0
...
1258 write(1, "5\n", 2) = 2
...
1258 stat("/bin/ls", {st_mode=S_IFREG|0755, st_size=110080, ...}) = 0
1258 access("/bin/ls", R_OK) = 0
1258 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f7301f40a10) = 1259
1259 open("file_c-6.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
1259 dup2(3, 1) = 1
1259 close(3) = 0
1259 execve("/bin/ls", ["ls"], [/* 19 vars */]) = 0
1259 write(1, "71\nbin\nfile_a-5.txt\nfile_b-5.txt"..., 110) = 110
1259 close(1) = 0
1259 munmap(0x7f0e81c56000, 4096) = 0
1259 close(2) = 0
1259 exit_group(0) = ?
1259 +++ exited with 0 +++
1258 <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 1259
1258 rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f7301570d40}, {0x4438a0, [], SA_RESTORER, 0x7f7301570d40}, 8) = 0
1258 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
1258 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1259, si_status=0, si_utime=0, si_stime=0} ---
1258 wait4(-1, 0x7ffd23d86e98, WNOHANG, NULL) = -1 ECHILD (No child processes)
1258 rt_sigreturn() = 0
1258 write(1, "5\n", 2) = 2
Dalam contoh terakhir ini, Anda melihat clone
proses baru (dari 1258 -> 1259), jadi sekarang kita sedang dalam proses. Pembukaan file_c-6.txt yang berarti bahwa kami telah mengevaluasi $((++i))
dalam subshell, dan eksekusi ls
dengan stdout-nya diatur ke file itu.
Akhirnya, kita melihat bahwa subproses keluar, kita menuai anak, lalu kita lanjutkan dengan tempat kita tinggalkan ... dengan $i
set ke 5, dan itulah yang kita gema lagi.
(Ingat perubahan variabel dalam suatu subproses tidak meresap ke proses induk, kecuali jika Anda melakukan sesuatu secara eksplisit pada induk untuk mengambil perubahan anak)