如何向 bash 脚本添加线程?

How to add threading to the bash script?

#!/bin/bash
cat input.txt | while read ips
do
    cmd="$(snmpwalk -v2c -c abc@123 $ips sysUpTimeInstance)"
    echo "$ips ---> $cmd"
    echo "$ips $cmd" >> out_uptime.txt
done

如何向这个 bash 脚本添加线程,我有大约 80000 个输入并且需要很多时间?

您可以通过&将任务发送到后台。如果您打算等待所有这些完成,您可以使用 wait 命令:

process_to_background &
echo Processing ...
wait
echo Done

如果您想等待一个(或几个)特定任务,您可以在后台获取给定任务的 pid

important_process_to_background &
important_pid=$!
while i in {1..10}; do
    less_important_process_to_background $i &
done

wait $important_pid
echo Important task finished

wait
echo All tasks finished

不过请注意:后台进程可能会弄乱输出,因为它们会 运行 异步。您可能希望使用 命名管道 来收集它们的输出。

  1. 简单的方法。假设输出的顺序不重要,and snmpwalk 的输出没有意义 if 它应该失败,放一个&& 在每个背景命令的末尾,除了最后一个命令应该在末尾有一个 &

    #!/bin/bash
    while read ips
    do
        cmd="$(nice snmpwalk -v2c -c abc@123 $ips sysUpTimeInstance)" &&
        echo "$ips ---> $cmd" &&
        echo "$ips $cmd" >> out_uptime.txt &
    done < input.txt
    
  2. 不太简单。如果 snmpwalk 可能会失败,并且还需要该输出,则去掉 && 并将代码用大括号括起来,{},然后是 &。要重定向附加输出以包括 标准错误 使用 &>>:

    #!/bin/bash
    while read ips
    do  {
        cmd="$(nice snmpwalk -v2c -c abc@123 $ips sysUpTimeInstance)"
        echo "$ips ---> $cmd"
        echo "$ips $cmd" &>> out_uptime.txt
        } &
    done < input.txt
    

    大括号可以包含更复杂的 if ... then ... else ... fi 语句,所有这些语句都将作为背景。


对于那些没有要测试的复杂 snmpwalk 命令的人来说,这里有一个类似的循环,它打印 1 到 5,但在 echo 命令之间随机休眠:

for f in {1..5}; do
    RANDOM=$f && 
    sleep $((RANDOM/6000)) &&
    echo $f &
done 2> /dev/null | cat

每次输出都相同(删除 RANDOM=$f && 以获得不同的输出),并且需要三秒才能 运行:

2
4
1
3
5

将其与不带 &&& 的代码 进行比较:

for f in {1..5}; do
    RANDOM=$f
    sleep $((RANDOM/6000))
    echo $f
done 2> /dev/null | cat

当 运行 时,代码需要 7 秒到 运行,输出为:

1
2
3
4
5