| 1 | #!/usr/bin/env bash |
| 2 | # |
| 3 | # Job control constructs: |
| 4 | # & terminator (instead of ;) |
| 5 | # $! -- last PID |
| 6 | # wait builtin (wait -n waits for next) |
| 7 | # |
| 8 | # Only interactive: |
| 9 | # fg |
| 10 | # bg |
| 11 | # %1 -- current job |
| 12 | |
| 13 | #### wait with nothing to wait for |
| 14 | wait |
| 15 | ## status: 0 |
| 16 | |
| 17 | #### wait -n with nothing to wait for |
| 18 | # The 127 is STILL overloaded. Copying bash for now. |
| 19 | wait -n |
| 20 | ## status: 127 |
| 21 | ## OK dash status: 2 |
| 22 | ## OK mksh status: 1 |
| 23 | |
| 24 | #### wait with invalid job ID |
| 25 | wait %nonexistent |
| 26 | ## status: 127 |
| 27 | ## OK dash status: 2 |
| 28 | |
| 29 | #### wait with invalid PID |
| 30 | wait %nonexistent |
| 31 | ## status: 127 |
| 32 | ## OK dash status: 2 |
| 33 | |
| 34 | #### Builtin in background |
| 35 | echo async & |
| 36 | wait |
| 37 | ## stdout: async |
| 38 | |
| 39 | #### External command in background |
| 40 | sleep 0.01 & |
| 41 | wait |
| 42 | ## stdout-json: "" |
| 43 | |
| 44 | #### Pipeline in Background |
| 45 | echo hi | { exit 99; } & |
| 46 | wait $! |
| 47 | echo status=$? |
| 48 | ## stdout: status=99 |
| 49 | |
| 50 | #### Wait sets PIPESTATUS |
| 51 | { echo hi; exit 55; } | { exit 99; } & |
| 52 | echo "pipestatus=${PIPESTATUS[@]}" |
| 53 | wait $! |
| 54 | echo status=$? |
| 55 | echo "pipestatus=${PIPESTATUS[@]}" |
| 56 | ## stdout-json: "pipestatus=\nstatus=99\npipestatus=55 99\n" |
| 57 | ## BUG bash stdout-json: "pipestatus=\nstatus=99\npipestatus=0\n" |
| 58 | ## N-I mksh stdout-json: "pipestatus=0\nstatus=99\npipestatus=0\n" |
| 59 | ## N-I dash stdout-json: "" |
| 60 | ## N-I dash status: 2 |
| 61 | |
| 62 | #### Brace group in background, wait all |
| 63 | { sleep 0.09; exit 9; } & |
| 64 | { sleep 0.07; exit 7; } & |
| 65 | wait # wait for all gives 0 |
| 66 | echo "status=$?" |
| 67 | ## stdout: status=0 |
| 68 | |
| 69 | #### Wait on background process PID |
| 70 | { sleep 0.09; exit 9; } & |
| 71 | pid1=$! |
| 72 | { sleep 0.07; exit 7; } & |
| 73 | pid2=$! |
| 74 | wait $pid1 |
| 75 | echo "status=$?" |
| 76 | wait $pid2 |
| 77 | echo "status=$?" |
| 78 | ## stdout-json: "status=9\nstatus=7\n" |
| 79 | |
| 80 | #### Wait on multiple specific IDs returns last status |
| 81 | { sleep 0.08; exit 8; } & |
| 82 | jid1=$! |
| 83 | { sleep 0.09; exit 9; } & |
| 84 | jid2=$! |
| 85 | { sleep 0.07; exit 7; } & |
| 86 | jid3=$! |
| 87 | wait $jid1 $jid2 $jid3 # NOTE: not using %1 %2 %3 syntax on purpose |
| 88 | echo "status=$?" # third job I think |
| 89 | ## stdout: status=7 |
| 90 | |
| 91 | #### wait -n |
| 92 | { sleep 0.09; exit 9; } & |
| 93 | { sleep 0.03; exit 3; } & |
| 94 | wait -n |
| 95 | echo "status=$?" |
| 96 | wait -n |
| 97 | echo "status=$?" |
| 98 | ## stdout-json: "status=3\nstatus=9\n" |
| 99 | ## N-I dash stdout-json: "status=2\nstatus=2\n" |
| 100 | ## N-I mksh stdout-json: "status=1\nstatus=1\n" |
| 101 | |
| 102 | #### Async for loop |
| 103 | for i in 1 2 3; do |
| 104 | echo $i |
| 105 | sleep 0.0$i |
| 106 | done & |
| 107 | wait |
| 108 | ## stdout-json: "1\n2\n3\n" |
| 109 | ## status: 0 |
| 110 | |
| 111 | #### Background process doesn't affect parent |
| 112 | echo ${foo=1} |
| 113 | echo $foo |
| 114 | echo ${bar=2} & |
| 115 | wait |
| 116 | echo $bar # bar is NOT SET in the parent process |
| 117 | ## stdout-json: "1\n1\n2\n\n" |