Sering ada kebingungan antara proses forking dan eksekusi.
Ketika Anda melakukannya pada prompt bash
shell.
$ sh -c 'exec env ps'
Proses P1 yang mengeluarkan $
prompt itu sedang menjalankan bash
kode. Itu bash
kode garpu proses baru P2 yang mengeksekusi /bin/sh
yang kemudian mengeksekusi /usr/bin/env
, yang kemudian mengeksekusi /bin/ps
.
Jadi P2 pada gilirannya dieksekusi kode bash
, sh
, env
dan ps
.
ps
(atau perintah lain seperti skrip yang akan kami gunakan di sini) tidak memiliki cara untuk mengetahui bahwa itu telah dieksekusi oleh env
perintah.
Yang bisa dilakukan adalah mencari tahu apa proses id induknya, yang dalam hal ini akan menjadi P1 atau 1
jika P1 telah mati dalam interval atau di Linux proses lain yang telah ditunjuk sebagai subreaper bukan 1
.
Ia kemudian dapat meminta sistem untuk perintah apa yang sedang dijalankan proses (seperti dengan readlink /proc/<pid>/exe
di Linux) atau argumen apa yang diteruskan ke perintah terakhir yang dijalankan (seperti dengan ps -o args= -p <pid>
).
Jika Anda ingin skrip Anda tahu apa yang memintanya, cara yang dapat diandalkan adalah meminta penyerang memberi tahu. Itu bisa dilakukan misalnya melalui variabel lingkungan. Misalnya script1
dapat ditulis sebagai:
#! /bin/sh -
INVOKER=$0 script2 &
Dan script2
:
#! /bin/sh -
printf '%s\n' "I was invoked by $INVOKER"
# and in this case, we'll probably find the parent process is 1
# (if not now, at least one second later) as script1 exited just after
# invoking script2:
ps -fp "$$"
sleep 1
ps -fp "$$"
exit
$INVOKER
akan ( umumnya ) berisi path ke script1
. Dalam beberapa kasus, ini mungkin merupakan jalur relatif, dan jalur tersebut akan relatif terhadap direktori kerja saat ini pada saat script1
dimulai. Jadi jika script1
mengubah direktori kerja saat ini sebelum memanggil script2
, script2
akan mendapatkan informasi yang salah tentang apa yang memanggilnya. Jadi mungkin lebih baik untuk memastikan $INVOKER
berisi path absolut (lebih disukai menjaga nama dasarnya) seperti dengan menulis script1
sebagai:
#! /bin/sh -
mypath=$(
mydir=$(dirname -- "$0") &&
cd -P -- "$mydir" &&
pwd -P) && mypath=$mypath/$(basename -- "$0") || mypath=$0
... some code possibly changing the current working directory
INVOKER=$mypath script2
Dalam shell POSIX, $PPID
akan berisi pid dari induk dari proses yang mengeksekusi shell pada saat inisialisasi shell. Setelah itu, seperti yang terlihat di atas, proses induk dapat berubah jika proses id $PPID
mati.
zsh
dalam zsh/system
modul, dapat meminta pid induk saat ini dari shell (sub-) saat ini dengan $sysparams[ppid]
. Dalam shell POSIX, Anda bisa mendapatkan ppid saat ini dari proses yang mengeksekusi penerjemah (dengan asumsi itu masih berjalan) dengan ps -o ppid= -p "$$"
. Dengan bash
, Anda bisa mendapatkan ppid dari shell (sub-) saat ini dengan ps -o ppid= -p "$BASHPID"
.