限制产生的子壳数量

时间:2013-06-21 13:26:39

标签: bash process limit subshell

我正在尝试限制在我用来嗅探内部网络以审核网络中的Linux服务器的脚本中生成的子shell数量。该脚本按预期工作,但由于我嵌套for循环的方式,它为每个网络生成255个子shell,因此它会因为有超过1000个进程产生而导致CPU死亡。我需要能够限制进程数量,并且由于变量在Sub Shell中失去了它们的价值,我无法找到一种方法来使其工作。再次,脚本工作,它只产生了一个进程 - 我需要限制它,比如说最多10个进程:

#!/bin/bash

FILE=/root/ats_net_final

for network in `cat $FILE`;do
                for ip in $network.{1..255};do
                        (
                                SYSNAME=`snmpwalk -v2c -c public -t1 -r1 $ip sysName.0 2>/dev/null | awk '{ print $NF }'`
                                SYSTYPE=`snmpwalk -v2c -c public -t1 -r1 $ip sysDescr.0 2>/dev/null | grep -o Linux`
                                if [ $? -eq 0 ];then
                                        echo "$SYSNAME"
                                        exit 0;
                                else
                                        echo "Processed $ip"
                                        exit 0
                                fi
                        ) &
                done
done

This解决方案我发现它有效,但不是我的情况,因为无论如何,它仍然会在限制进程的逻辑之前产生进程。我想也许我只是在看代码太久了,这只是一个简单的逻辑问题而且我把东西放在错误的区域,或者顺序错误。


接受的答案:

我接受了huitseeker的回答。他能够为我提供逻辑运作方向,让我能够使用它。最后的剧本:

#!/bin/bash

FILE=/root/ats_net_final

for network in `cat $FILE`;do
        #for ip in $network.{1..255};do
        for ip in {1..255};do
            (
                ip=$network.$ip
                SYSNAME=`snmpwalk -v2c -c public -t1 -r1 $ip sysName.0 2>/dev/null | awk '{ print $NF }'`
                SYSTYPE=`snmpwalk -v2c -c public -t1 -r1 $ip sysDescr.0 2>/dev/null | grep -o Linux`
                if [ $? -eq 0 ];then
                    echo "$SYSNAME"
                    exit 0;
                else
                    echo "Processed $ip"
                    exit 0
                fi
            ) &
            if (( $ip % 10 == 0 )); then wait; fi
        done
        wait
done

2 个答案:

答案 0 :(得分:2)

将并发子单元数限制为10的简单方法是:

for ip in $(seq 1 255);do
  (<whatever you did with $ip in the subshell here, do with $network.$ip instead >) &
  if (( $ip % 10 == 0 )); then wait; fi
done
wait

最后一次等待是有用的,不要让内环的最后一轮的子壳与下一轮外圈的第一轮中创建的子壳重叠。

答案 1 :(得分:1)

我想我找到了更好的解决方案。我使用实现了

#!/usr/bin/make -f

IPFILE := ipfile
IPS:=$(foreach ip,$(shell cat $(IPFILE)),$(foreach sub,$(shell seq 1 1 254),$(ip).$(sub)))

all: $(IPS)

$(IPS):
        SYSNAME=`snmpwalk -v2c -c public -t1 -r1 $@ sysName.0 2>/dev/null | awk '{ print $$NF }'`; \
        SYSTYPE=`snmpwalk -v2c -c public -t1 -r1 $@ sysDescr.0 2>/dev/null | grep -o Linux`; \
        if [ $$? -eq 0 ]; then \
          echo "$$SYSNAME"; \
        else \
          echo "Processed $@"; \
        fi

IP的第一部分(例如192.168.1)应放在ipfile中。然后它将所有IP地址生成到变量IPS中(如192.168.1.1 ... 192.168.1.254 ...)。

这些行可以复制到例如test.mak并为文件添加执行权限。如果将其作为./test.mak运行,则它将逐个处理IPS中的IP。但如果它以./test.mak -j 10运行,那么它将同时处理10个IP。它也可以./test.mak -j 10 -l 0.5运行。它将运行最多10个进程或直到系统负载达到0.5。