Những gì awk system()
nên trả lại được chỉ định kém .
Điều có vẻ phổ biến trong các lần awk
triển khai là khi thoát bình thường, nó trả về mã thoát (số được chuyển cho exit(3)
modulo 256), nhưng khi quá trình shell bị giết bởi tín hiệu, có rất nhiều hành vi khác nhau.
Cũng lưu ý rằng trong khi chức năng C system(3)
có nghĩa là để bỏ qua SIGINT (và SIGQUIT) trong các phụ huynh, nó không phải là rất rõ ràng (với tôi ít nhất) mà yêu cầu cũng áp dụng cho awk
's system()
. Một số awk
triển khai (như mawk
) sẽ chết vì SIGINT đó (đó cũng là hành vi tôi muốn thấy vì tôi không thích CTRL-C của mình bị bỏ qua chỉ vì awk
tình cờ chạy system()
chức năng), một số (như gawk
triển khai truyền thống) sẽ không
Cũng lưu ý rằng một số shell có thể chặn một số tín hiệu đó và cuối cùng gọi exit()
sẽ ảnh hưởng đến hành vi (ví dụ như thảo luận trong các bình luận về shell Bourne), đó là lý do tại sao tôi sử dụng exec
trong các ví dụ bên dưới để xóa shell khỏi vòng lặp.
Đối với giá trị được trả về bởi system()
(thậm chí còn có nhiều biến thể hơn nếu bạn xem xét close()
1 ) theo SIGINT, chúng tôi thấy:
$ nawk 'BEGIN {print system("exec kill -s INT $$")}'
0.0078125
$ bwk-awk 'BEGIN {print system("exec kill -s INT $$")}'
0.0078125
$ mawk 'BEGIN {print system("exec kill -s INT $$")}'
130
$ gawk 'BEGIN {print system("exec kill -s INT $$")}'
0
0.0078125
trở thành 2 / 256
(đối với một SEGV
trong số đó 11
, bạn sẽ nhận được 0,542969 ((128 + 11) / 256) nếu một lõi bị đổ, 0,0429688 (11/256) nếu không), nawk
được nawk
tìm thấy trên Solaris 10 hoặc 11, hoặc cổng Linux của nó trong gia truyền toolchest, bwk-awk
được sự awk
duy trì bởi Brian Kernighan mình (các K
trong awk
) cơ sở cho việc awk
tìm thấy trên một số BSDs (ở đây được thử nghiệm trên Debian GNU / Linux). /usr/xpg4/bin/awk
trên Solaris 11 hành xử như thế nào gawk
.
Vì vậy, dựa trên giá trị s
được trả về bởi system(3)
(một số nguyên nơi bit 0-6 là số tín hiệu, cắn 7 lõi-bit, và bit 8 đến 15 mã thoát), awk
's system()
lợi nhuận trên một trong hai:
s / 256
( awk
thực hiện truyền thống ),
int(s/256)
( gawk
),
- hoặc trong
mawk
, biến đổi tương tự như được thực hiện bởi các shell như Bourne hoặc C-shell chẳng hạn ( (s&127)+128
nếu bị giết, s>>8
nếu không), ngoại trừ nếu một lõi bị đổ, bạn nhận được (s&127)+256
thay vì (s&127)+128
(giá trị là (s&255)+128
).
Vì vậy, ở đây, bạn có thể làm thay thế:
awk 'BEGIN{print system("trap exit\\ 1 INT; sleep 10")}'
Nhưng nó vẫn awk
sẽ bị giết với một số awk
triển khai như thế nào mawk
. Nếu bạn sh
là bash
hoặc yash
, bạn có thể làm:
awk 'BEGIN{print system("set -m; sleep 10; exit")}'
Vì vậy, sleep
được chạy trong nhóm quy trình riêng của mình (và chỉ có nó mới có SIGINT).
Một cách khác có thể là bỏ qua SIGINT trước khi gọi awk
. Tuy nhiên, hầu hết các shell (và đó là yêu cầu POSIX) không thể thay đổi trình xử lý tín hiệu nếu tín hiệu đã bị bỏ qua khi bắt đầu. Vì vậy, những thứ như:
(
trap '' INT
awk 'BEGIN{print system("trap exit\\ 1 INT; sleep 10; exit")}'
)
Sẽ không làm việc. zsh
mặc dù không có giới hạn (tự gây ra), vì vậy nếu bạn biết zsh
là có sẵn, bạn có thể làm:
(
trap '' INT
awk 'BEGIN{print system("exec zsh -c \"TRAPINT() exit 1; sleep 10\"")}'
)
Điều này sẽ làm việc cho dù awk
là mawk
, gawk
hoặc khác và sẽ tránh phải lộn xộn với kiểm soát công việc. Tuy nhiên, tại thời điểm này, sẽ đáng để xem xét sử dụng perl
/ python
/ ruby
... thay vì awk
nơi bạn có thể điều chỉnh việc xử lý tín hiệu theo nhu cầu của mình.
Ghi chú
1 Khi close()
một đường ống, như trong:
awk 'BEGIN {cmd = "kill -s INT $$"; cmd | getline; print close(cmd)}'
Đầu tiên, lần này ^C
làm gián đoạn awk
trong tất cả các triển khai tôi đã thử (không có yêu cầu như vậy để bỏ qua SIGINT / SIGQUIT cho popen(3)
/ pclose(3)
(một cách tự nhiên để thực hiện điều đó getline
) như đã có system(3)
).
Nhưng khi nói đến trạng thái thoát ( s
giá trị được trả về bởi pclose(3)
/ waitpid(2)
like cho system()
ở trên), chúng ta thấy:
- Solaris
nawk
: không hoạt động, bạn không thể gọi close()
như thế trong Solaris nawk
.
/usr/xpg4/bin/awk
trên Solaris. Trả về luôn luôn 0, ngay cả khi exit(1)
được thực hiện theo quy trình. Rõ ràng là một lỗi phù hợp.
gawk
và bwk-awk
: cho s
( exit 1
cho 256, bị giết bởi SIGINT cho 2, bị giết bởi SIGSEGV là 11 với lõi cho 139).
mawk
: giống như đối với system()
, có vẻ như mawk
là triển khai duy nhất đưa ra bất kỳ suy nghĩ nào về điều đó.