3

我正在尝试限制脚本中生成的子shell 的数量,该脚本用于嗅探我们的内部网络以审计我们网络中的 Linux 服务器。该脚本按预期工作,但由于我嵌套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

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


接受的答案:

我已经接受了 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
4

2 回答 2

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

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

于 2013-06-21T14:08:03.640 回答
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。

于 2013-07-15T20:07:24.277 回答