รอการใช้คำสั่งใน Linux หรือไม่


16
#!/bin/bash
function back()
{
    sleep $1
    exit $2
}
back $1 $2 &
b=$!
if `wait $!`;then
    echo success
else
    echo failure
fi
bash-3.00# ./back 300 0
failure
bash-3.00# ./back 300 1
failure

ผมคาดหวังว่าsuccessเป็นสถานะออกเมื่อฉันส่ง 0 failureแต่ฉันยังคงได้รับ

นอกจากนี้waitไม่ต้องรอเป็นเวลา 300 วินาที แต่ฉันได้รับข้อความทันที ฉันถือว่า$!เป็นลูกของ$$สคริปต์ ไม่ใช่เหรอ

สามารถจับสถานะทางออกของการรอได้exit_status=$(wait $!)หรือไม่?

if ! ((exit_status));then
    echo sucess
else
    failure
fi

คำตอบ:


20

ปัญหาคือคุณกำลังออกwaitใน subshell:

if `wait $!`;then

เพราะwaitมันเป็น builtin ไม่ใช่คำสั่งมันทำงานบนsubshellไม่ใช่ shell ปัจจุบันของคุณ

ผลลัพธ์ที่คุณจะเห็น แต่ไม่ใช่:

wait: pid 12344 is not a child of this shell

... ที่มีสถานะส่งคืน 1

ในการทำแบบทดสอบคุณจะต้องทำโดยไม่ต้องใช้ subshell

#!/bin/bash
function back()
{
  sleep $1
  exit $2
}
back $1 $2 &
b=$!

wait $b && echo success || echo failure

สิ่งนี้จะให้ผลลัพธ์ที่คุณคาดหวังและรอตราบเท่าที่คุณคาดหวัง:

$ time ./test.sh 3 0
success
./test.sh 3 0  0.00s user 0.01s system 0% cpu 3.012 total
$ time ./test.sh 3 1
failure
./test.sh 3 1  0.00s user 0.01s system 0% cpu 3.012 total

คุณสามารถตรวจสอบสถานะการออกของคำสั่งใด ๆ ด้วย$?:

$ /bin/true
$ echo $?
0
$ /bin/false
$ echo $?
1

สคริปต์ของคุณมีข้อผิดพลาดอื่น ๆ อีกสองสามข้อ #!บรรทัดของคุณมีรูปแบบไม่ถูกต้องซึ่งฉันได้แก้ไขแล้ว คุณสามารถกำหนด$!ไปแต่ไม่ได้ใช้$b$b


12

ถอด backticks

เช่นเดียวกับที่คุณกำลังดำเนินการwaitใน subshell ซึ่งไม่สามารถเข้าถึงงานของ parent shell ดังนั้นมันจะล้มเหลวทันที


หากคุณต้องการสถานะทางออกให้รับค่า$?ทันทีหลังจากรอ

command_here &
wait
status=$?

2

การลบ backticks จะทำให้โปรแกรมทำงานได้ แต่ไม่ใช่ทั้งหมดเนื่องจากเหตุผลที่ระบุไว้แล้ว มันเป็นความจริงที่waitล้มเหลวในทันทีเพราะมันทำงานใน subshell และไม่สามารถเข้าถึงกระบวนการของผู้ปกครอง แต่โปรแกรมจะไม่ทำงานตามที่คาดไว้แม้ว่าคุณจะใช้คำสั่งที่ทำงาน

ifคำสั่งรันโปรแกรมและการตรวจสอบถ้าออกจากสถานะของมันเป็นศูนย์หรือไม่เป็นศูนย์ เมื่อคุณใช้ backticks คำสั่ง if จะใช้ผลลัพธ์ของกระบวนการพยายามเรียกใช้เป็นโปรแกรมจากนั้นใช้รหัสออกสำหรับกระบวนการนั้น ดังนั้นโปรแกรมจะไม่ล้มเหลวเพราะwaitล้มเหลว แต่มันล้มเหลวเพราะwaitไม่ได้สร้างผลลัพธ์ใด ๆ

คุณสามารถทำให้สคริปต์ทำงานได้โดยใช้echoภายใน backticks:

if `echo wait $!`; then
    echo success
else
    echo failure
fi

หรือเพียงลบ backticks; ง่ายขึ้นสำหรับทุกคน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.