阅读时猛击:输出问题

时间:2014-05-22 07:46:26

标签: sql bash loops for-loop while-loop

更新: 初始问题: 有一个读取循环打印每行读取 答案:完成一次<<< “$ 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

为什么不能处理这个?

4 个答案:

答案 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参数。

http://www.gnu.org/software/parallel/

答案 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将等待所有已启动的进程完成。