Các quy trình có thể gọi cuộc gọi _exit()
hệ thống (trên Linux, xem thêm exit_group()
) với một đối số nguyên để báo cáo mã thoát cho cha mẹ của chúng. Mặc dù đó là một số nguyên, nhưng chỉ có 8 bit có ý nghĩa nhỏ nhất có sẵn cho cha mẹ (ngoại trừ đó là khi sử dụng waitid()
hoặc xử lý trên SIGCHLD trong cha mẹ để lấy mã đó , mặc dù không có trên Linux).
Phụ huynh thường sẽ làm một wait()
hoặc waitpid()
để lấy trạng thái của con họ như một số nguyên (mặc dù waitid()
với ngữ nghĩa hơi khác nhau cũng có thể được sử dụng).
Trên Linux và hầu hết các Unice, nếu quá trình kết thúc bình thường, các bit 8 đến 15 của số trạng thái đó sẽ chứa mã thoát như được chuyển đến exit()
. Nếu không, thì 7 bit có ý nghĩa nhỏ nhất (0 đến 6) sẽ chứa số tín hiệu và bit 7 sẽ được đặt nếu một lõi bị đổ.
perl
's $?
ví dụ chứa con số đó là do waitpid()
:
$ perl -e 'system q(kill $$); printf "%04x\n", $?'
000f # killed by signal 15
$ perl -e 'system q(kill -ILL $$); printf "%04x\n", $?'
0084 # killed by signal 4 and core dumped
$ perl -e 'system q(exit $((0xabc))); printf "%04x\n", $?'
bc00 # terminated normally, 0xbc the lowest 8 bits of the status
Các shell giống như Bourne cũng làm cho trạng thái thoát của lệnh chạy cuối cùng trong $?
biến của riêng chúng . Tuy nhiên, nó không chứa trực tiếp số được trả về waitpid()
, mà là một phép biến đổi trên nó và nó khác nhau giữa các shell.
Điều phổ biến giữa tất cả các shell là $?
chứa 8 bit thấp nhất của mã thoát (số được truyền tới exit()
) nếu quá trình kết thúc bình thường.
Nơi nó khác nhau là khi quá trình được kết thúc bởi một tín hiệu. Trong mọi trường hợp và theo yêu cầu của POSIX, số này sẽ lớn hơn 128. POSIX không chỉ định giá trị có thể là bao nhiêu. Trong thực tế, trong tất cả các vỏ giống như Bourne mà tôi biết, 7 bit thấp nhất $?
sẽ chứa số tín hiệu. Nhưng, đâu n
là số tín hiệu,
trong tro, zsh, pdksh, bash, vỏ Bourne, $?
là 128 + n
. Điều đó có nghĩa là trong những vỏ, nếu bạn nhận được một $?
số 129
, bạn không biết liệu đó là vì quá trình này đã thoát với exit(129)
hoặc cho dù đó đã bị giết bởi các tín hiệu 1
( HUP
trên hầu hết các hệ thống). Nhưng lý do là các shell đó, khi chúng tự thoát, mặc định trả về trạng thái thoát của lệnh đã thoát cuối cùng. Bằng cách đảm bảo $?
không bao giờ lớn hơn 255, điều đó cho phép có trạng thái thoát nhất quán:
$ bash -c 'sh -c "kill \$\$"; printf "%x\n" "$?"'
bash: line 1: 16720 Terminated sh -c "kill \$\$"
8f # 128 + 15
$ bash -c 'sh -c "kill \$\$"; exit'; printf '%x\n' "$?"
bash: line 1: 16726 Terminated sh -c "kill \$\$"
8f # here that 0x8f is from a exit(143) done by bash. Though it's
# not from a killed process, that does tell us that probably
# something was killed by a SIGTERM
ksh93
, $?
Là 256 + n
. Điều đó có nghĩa là từ một giá trị của $?
bạn có thể phân biệt giữa một quá trình bị giết và không bị giết. Các phiên bản mới hơn ksh
, khi thoát, nếu $?
lớn hơn 255, sẽ tự giết mình với cùng một tín hiệu để có thể báo cáo trạng thái thoát tương tự cho cha mẹ của nó. Mặc dù nghe có vẻ là một ý tưởng hay, điều đó có nghĩa là ksh
sẽ tạo ra một bãi chứa lõi bổ sung (có khả năng ghi đè lên cái khác) nếu quá trình bị giết bởi tín hiệu tạo lõi:
$ ksh -c 'sh -c "kill \$\$"; printf "%x\n" "$?"'
ksh: 16828: Terminated
10f # 256 + 15
$ ksh -c 'sh -c "kill -ILL \$\$"; exit'; printf '%x\n' "$?"
ksh: 16816: Illegal instruction(coredump)
Illegal instruction(coredump)
104 # 256 + 15, ksh did indeed kill itself so as to report the same
# exit status as sh. Older versions of `ksh93` would have returned
# 4 instead.
Nơi bạn thậm chí có thể nói có một lỗi là ksh93
nó tự giết chết ngay cả khi $?
xuất phát từ return 257
một chức năng:
$ ksh -c 'f() { return "$1"; }; f 257; exit'
zsh: hangup ksh -c 'f() { return "$1"; }; f 257; exit'
# ksh kills itself with a SIGHUP so as to report a 257 exit status
# to its parent
yash
. yash
đưa ra một sự thỏa hiệp. Nó trở lại 256 + 128 + n
. Điều đó có nghĩa là chúng ta cũng có thể phân biệt giữa một quá trình bị giết và một quá trình kết thúc đúng. Và khi thoát ra, nó sẽ báo cáo 128 + n
mà không phải tự sát và các tác dụng phụ có thể có.
$ yash -c 'sh -c "kill \$\$"; printf "%x\n" "$?"'
18f # 256 + 128 + 15
$ yash -c 'sh -c "kill \$\$"; exit'; printf '%x\n' "$?"
8f # that's from a exit(143), yash was not killed
Để nhận được tín hiệu từ giá trị của $?
, cách di động là sử dụng kill -l
:
$ /bin/kill 0
Terminated
$ kill -l "$?"
TERM
(đối với tính di động, bạn không bao giờ nên sử dụng số tín hiệu, chỉ tên tín hiệu)
Trên các mặt trận không Bourne:
csh
/ tcsh
và fish
giống như trình bao Bourne ngoại trừ trạng thái ở trong $status
thay vì $?
(lưu ý zsh
cũng đặt $status
để tương thích với csh
(ngoài $?
)).
rc
: trạng thái thoát $status
cũng vậy, nhưng khi bị giết bởi tín hiệu, biến đó chứa tên của tín hiệu (giống sigterm
hoặc sigill+core
nếu lõi được tạo) thay vì một số, đó là một bằng chứng khác về thiết kế tốt của lớp vỏ đó .
es
. trạng thái thoát không phải là một biến. Nếu bạn quan tâm đến nó, bạn chạy lệnh như:
status = <={cmd}
sẽ trả về một số hoặc sigterm
hoặc sigsegv+core
thích rc
.
Có lẽ cho đầy đủ, chúng ta nên đề cập đến zsh
's $pipestatus
và bash
' s $PIPESTATUS
mảng có chứa các trạng thái thoát của các thành phần của đường ống ngoái.
Và cũng để hoàn thiện, khi nói đến các hàm shell và các tệp có nguồn gốc, theo mặc định các hàm sẽ trả về trạng thái thoát của lệnh chạy cuối cùng, nhưng cũng có thể đặt trạng thái trả về rõ ràng với return
nội dung. Và chúng tôi thấy một số khác biệt ở đây:
bash
và mksh
(kể từ R41, một hồi quy ^ Wchange rõ ràng được giới thiệu có chủ ý ) sẽ cắt số (dương hoặc âm) thành 8 bit. Vì vậy, ví dụ return 1234
sẽ được đặt $?
thành 210
, return -- -1
sẽ được đặt $?
thành 255.
zsh
và pdksh
(và các dẫn xuất khác mksh
) cho phép mọi số nguyên thập phân 32 bit đã ký (-2 31 đến 2 31 -1) (và cắt số đó thành 32 bit ).
ash
và yash
cho phép mọi số nguyên dương từ 0 đến 2 31 -1 và trả về lỗi cho bất kỳ số nào trong số đó.
ksh93
cho return 0
đến return 320
thiết lập $?
như là, nhưng đối với bất cứ điều gì khác, cắt xén đến 8 bit. Coi chừng như đã đề cập rằng việc trả về một số trong khoảng từ 256 đến 320 có thể gây ra ksh
tự tử khi thoát.
rc
và es
cho phép trả lại bất cứ thứ gì kể cả danh sách.
Cũng lưu ý rằng một số vỏ cũng sử dụng các giá trị đặc biệt của $?
/ $status
báo cáo một số điều kiện lỗi đó không phải là trạng thái thoát của một quá trình, như 127
hoặc 126
cho command not found hoặc không thực thi (hoặc lỗi cú pháp trong một tập tin nguồn) ...
killall myScript
tác phẩm của bạn , do đó, sự trở lại của killall (chứ không phải của tập lệnh!) là 0. Bạn có thể đặtkill -x $$
[x là số tín hiệu và $$ thường được mở rộng bởi trình bao tới PID của tập lệnh đó (hoạt động trong sh, bash, ...)] Bên trong tập lệnh và sau đó kiểm tra lõi thoát của nó là gì.