lukuluku lukuluku - 3 years ago 95
Linux Question

Bash redirect vs. pipe

I have following bash script:

#!/bin/bash

trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM

proxy_list="${1}"
url="google.com"
pool=5
timeout=2

check_proxy() {
local socks_proxy="${1}"
for retry in {0..2}; do
time_connect="$(curl ${url} --socks5 ${socks_proxy} -m${timeout} -o /dev/null -s -w %{time_connect})"
if [ $? -eq 0 ]; then
echo "${socks_proxy} (${time_connect}s) retries=${retry}"
break
fi
done
}

while read proxy; do
while true; do
if [ "$(jobs -rp | wc -l)" -lt "${pool}" ]; then
check_proxy "${proxy}" &
break
fi
wait -n
done
done < "${proxy_list:-/dev/stdin}"

wait


The script will either use the filename (
${1}
) as input, or stdin if no positional parameter was provided.

(PIPE) If I run the script as follows and try to kill it with CTRL+C during runtime:

cut -f1 -d' ' data/socks_tested_sorted.list | ./curl_socks_tester.sh


I get this error and the script continues running:


./curl_socks_tester.sh: line 1: kill: (-21325) - No such process


(REDIRECT) Alternatively running the command like this and killing the script using CTRL+C:

./curl_socks_tester.sh <(cut -f1 -d' ' data/socks_tested_sorted.list)


The script stops and I get following message:


^CTerminated


Why is the trap able to kill all child-processes when using redirect but it fails using a pipe?

Answer Source

The way bash runs jobs, the first link in the pipe-line becomes the group leader (as you should be able to verify with ps).

Consequently, in:

cut -f1 -d' ' data/socks_tested_sorted.list | ./curl_socks_tester.sh

./curl_socks_tester.sh is not the group leader and so kill -- -$$ from it is invalid.

You can only use kill -- -$$ in a script if you can be sure the shell script is the leader of its process group.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download