更新: 初始问题: 有一个读取循环打印每行读取 答案:完成一次<<< “$ VAR” 后续问题: 我可能需要一些关于SHELL代码的解释: 我有这个:
temp_ip=$($mysql --skip-column-names -h $db_address -u $db_user -p$db_passwd $db_name -e "select ip_routeur,code_site from $db_vtiger_table where $db_vtiger_table.ip_routeur NOT IN (select ip from $db_erreur_table);")
结果看起来像这样:
<ip1> <site1>
<ip2> <site2>
<ip3> <site3>
<ip4> <site4>
最多5000个ip_address
我做了一个“while循环”:
while [ `find $proc_dir -name snmpproc* | wc -l` -ge "$max_proc_snmpget" ];do
{
echo "sleeping, fping in progress";
sleep 1;
}
done
temp_ip=$($mysql --skip-column-names -h $db_address -u $db_user -p$db_passwd $db_name -e "select ip_routeur,code_site from $db_vtiger_table where $db_vtiger_table.ip_routeur NOT IN (select ip from $db_erreur_table);")
while read ip codesite;do
{
sendSNMPGET $ip $snmp_community $code_site &
}
done<<<"$temp_ip"
sendSNMPGET函数是:
sendSNMPGET() {
touch $procdir/snmpproc.$$
hostname=`snmpget -v1 -c $2 $1 sysName.0`
if [ "$hostname" != "" ]
then
echo "hi test"
fi
rm -f $procdir/snmpproc.$$
$ max_proc_snmpget设置为30 在执行时,读取正常,不再在屏幕上打印,但子进程似乎迷失方向
hi
hi
hi
hi
hi
hi
hi
hi
hi
hi
hi
hi
./scan-snmp.sh: fork: Resource temporarily unavailable
./scan-snmp.sh: fork: Resource temporarily unavailable
./scan-snmp.sh: fork: Resource temporarily unavailable
./scan-snmp.sh: fork: Resource temporarily unavailable
为什么不能处理这个?
答案 0 :(得分:3)
如果temp_ip
包含您要阅读的文件的名称,请使用:
done<"$temp_ip"
在您的情况下,temp_ip
似乎不是文件名,但包含您想要的实际数据。在这种情况下,请使用:
done<<<"$temp_ip"
请注意将变量放在双引号内。这可以保护数据免受shell的单词拆分,从而导致用空格替换新的行字符。
在bash中,像<"$temp_ip"
这样的表达式称为重定向。在这种情况下,意味着while
循环将从名为$temp_ip
的文件中获取其标准输入。
表达式<<<"$temp_ip"
称为 here string 。在这种情况下,这意味着while
循环将从变量$temp_ip
中的数据获得其标准输入。
man bash
中有关重定向和此处字符串的详细信息。
答案 1 :(得分:2)
或者您可以直接解析初始命令的输出:
$mysql --skip-column-names -h $db_address -u $db_user -p$db_passwd $db_name -e "select ip_routeur,code_site from $db_vtiger_table where $db_vtiger_table.ip_routeur NOT IN (select ip from $db_erreur_table) | \
while read ip codesite
do
...
done
如果你想提高性能并并行运行5000个SNMPGET中的一些,我建议使用这样的GNU Parallel(here):
$mysql --skip-column-names -h $db_address -u $db_user -p$db_passwd $db_name -e "select ip_routeur,code_site from $db_vtiger_table where $db_vtiger_table.ip_routeur NOT IN (select ip from $db_erreur_table) | parallel -k -j 20 -N 2 sendSNMPGET {1} $snmp_community {2}
-k
将按顺序保持并行输出。 -j 20
一次最多可并行运行20个SNMPGET。 -N 2
表示从每个作业的mysql
输出中获取2个参数(即ip和codesite)。 {1}和{2}是您的ip和codesite参数。
答案 2 :(得分:1)
我建议不存储结果值,但直接使用它:
while read ip codesite
do
sendSNMPGET "$ip" "$snmp_community" "$code_site" &
done < <(
"$mysql" --skip-column-names -h "$db_address" -u "$db_user" -p"$db_passwd" "$db_name" \
-e "select ip_routeur,code_site from $db_vtiger_table where $db_vtiger_table.ip_routeur NOT IN (select ip from $db_erreur_table);")
这样你就可以在子shell中启动mysql命令,并使用它的输出作为while循环的输入(类似于管道,这里也是一个选项)。
但我发现该代码存在一些问题:如果你真的在后台启动每个sendSNMPGET
命令,很快就会对你的计算机造成很大的负担。对于每行,您将启动另一个活动后台进程。这可能会使您的机器变慢到无法使用的程度。
我建议不要一次运行超过20个后台进程。
答案 3 :(得分:0)
由于您似乎不喜欢我使用GNU Parallel的答案,我将向您展示一种非常简单的并行方式,而无需安装...
#!/bin/bash
MAX=8
j=0
while read ip code
do
(sleep 5; echo $ip $code) & # Replace this with your SNMPGET
((j++))
if [ $j -eq $MAX ]; then
echo -n Pausing with $MAX processes...
j=0
wait
fi
done < file
wait
这将启动最多8个进程(您可以更改它),然后等待它们完成,然后再启动另一个进程8.您已经看到了如何将mysql
内容提供给其中的其他响应者。脚本的倒数第二行......
关键是wait
将等待所有已启动的进程完成。