简体   繁体   English

嵌套for循环,设置变量以及是否在批处理脚本中

[英]nested for loop, set variable and if else in a batch script

I am trying to make a batch script which will write specific IP addresses in a file. 我正在尝试制作一个批处理脚本,该脚本将在文件中写入特定的IP地址。 I have a txt file (created by one python script) having a list of IP addresses (one in each new-line), Now I need to ping each of these IPs using for loop, check if the TTL value is between 100 to 128 (windows hosts) and write the IP addresses to a new file. 我有一个txt文件(由一个python脚本创建),具有一个IP地址列表(每个换行中一个),现在我需要使用for循环ping通这些IP,检查TTL值是否在100到128之间(Windows主机)并将IP地址写入新文件。 I've been trying to adjust into setting the variables and for loops but this all becomes too complex to run. 我一直试图调整以设置变量和for循环,但这一切都变得太复杂而无法运行。
So far I've reached:- 到目前为止,我已经达到:-
EDIT: corrected below command 编辑:在命令下方更正

for /f %i in (ip.txt) do ping -n 1 %i | find "TTL"

This will give me multiple lines Ping output, showing here only for single line (I am using 4.2.2.2 just for example) 这将给我多行Ping输出,此处仅显示单行(例如,我使用的是4.2.2.2)

Reply from 4.2.2.2: bytes=32 time=1 ms ttl=45

If I do ping to single IP I can pick the TTL field but not TTL's exact value 如果我对单个IP执行ping操作,则可以选择TTL字段,但不能选择TTL的确切值

for /f "tokens=6 delims= " %a in ('ping -n 1 4.2.2.2 ^| find "TTL"') do echo %a

It gives me the value TTL=45 whereas I needed 45 for the comparison. 它给我的值为TTL=45而我需要45进行比较。 I read about setlocal enabledelayedexpansion which is useful, but I am not able to combine these all into a single line and use set variables and use IF-ELSE loops. 我读到了有用的setlocal enabledelayedexpansion ,但我无法将它们全部合并成一行,无法使用set变量和IF-ELSE循环。
Plz give a little description on how to achieve the IP selection. 请简要介绍如何实现IP选择。

EDITED BY ME AFTER MAKING BATCH SCRIPT SOLUTION:- 制作批处理脚本解决方案后,由我编辑:
This batch script will ping every IP address given in the ips.txt file. 此批处理脚本将ping ips.txt文件中给定的每个IP地址。 Find the TTL value, if TTL value is equal to 128, it'll run a command NBTSTAT -A ip-address (for finding the GROUP information) and store it in a nbt_query_op.txt file. 查找TTL值,如果TTL值等于128,它将运行命令NBTSTAT -A ip-address (用于查找GROUP信息)并将其存储在nbt_query_op.txt文件中。
This file will be searched for existing results before firing the NBTSTAT command for every IP Address and if the result for a specific IP is not found in the file, NBTSTAT will be fired. 在为每个IP地址触发NBTSTAT命令之前,将在该文件中搜索现有结果,如果在文件中未找到特定IP的结果,则将触发NBTSTAT。
Note that variables should be referenced enclosed with ! 请注意变量应以括起来引用 characters, !TTL! 字符!TTL! , !ip1! ,!ip1! , !ERRORLEVEL! !!错误级别! . Further, thanks to Mr. RGuggisberg too for providing pointers. 此外,还要感谢RGuggisberg先生提供的指导。

@echo off
setlocal EnableDelayedExpansion
for /f %%i in (ips.txt) do (
for /f "tokens=6 delims= " %%a in ('ping -n 1 %%i ^| find "TTL"') do (
    for /f "tokens=2 delims==" %%b in ('echo.%%a') do set ttl=%%b
    echo %%i has TTL:- !ttl!
    if !TTL! == 128      (set ip1=%%i
                 echo        SELECTED IP- !ip1! TTL- !TTL!
                 findstr /c:!ip1! nbt_query_op.txt
                 if not !ERRORLEVEL! ==0 echo !ip1!>>nbt_query_op.txt && nbtstat -A !ip1! | find "GROUP">>nbt_query_op.txt
                     )
                                          )
)


Thanks, 谢谢,
kriss 克里斯

This will do what you are asking. 这将满足您的要求。 Modify as needed when you migrate to your first example. 迁移到第一个示例时,根据需要进行修改。

for /f "tokens=6 delims= " %a in ('ping -n 1 4.2.2.2 ^| find "TTL"') do for /f "tokens=2 delims==" %b in ('echo.%a') do echo %b

BTW, the first FOR loop in your post is incomplete. 顺便说一句,您帖子中的第一个FOR循环不完整。 I think you meant 我想你是说

for /f %i in (ip.txt) do ping -n 1 %i | find "TTL"

In vbscript you can do something like this : 在vbscript中,您可以执行以下操作:

strHost = "4.2.2.2"
if Ping(strHost) = True then
    Wscript.Echo "Host " & strHost & " contacted"
Else
    Wscript.Echo "Host " & strHost & " could not be contacted"
end if
'***************************************************************************************
Function Ping(strHost)
    dim objPing, objRetStatus
    set objPing = GetObject("winmgmts:{impersonationLevel=impersonate}").ExecQuery _
      ("select * from Win32_PingStatus where address = '" & strHost & "'")
    for each objRetStatus in objPing
        if IsNull(objRetStatus.StatusCode) or objRetStatus.StatusCode <> 0 then
            Ping = False
            WScript.Echo "Status code is " & objRetStatus.StatusCode
        else
            Ping = True
            Msg = Msg & " Pingging " & strHost & vbCrlf & vbCrlf 
            Msg = Msg & "Bytes = " & objRetStatus.BufferSize & vbCrlf 
            Msg = Msg & "Time (ms) = " & objRetStatus.ResponseTime & vbCrlf 
            Msg = Msg & "TTL (s) = "  & objRetStatus.ResponseTimeToLive 
        end if
    next
    Wscript.echo Msg
End Function 
'***************************************************************************************

EDIT : On 30/06/2016 @ 19:11 编辑:30/06/2016 @ 19:11

I tested with this file : file.txt 我测试了这个文件:file.txt

 4.2.2.2 www.google.com www.google.fr www.facebook.com www.stackoverflow.com www.yahoo.com www.yahoo.fr www.developpez.net 

this batch file : 这个批处理文件:

@echo off
Title Get TTL from IP adress
set vbsfile=%Tmp%\%~n0.vbs
set IP_File=E:\vb-ping\ip.txt
set LogFile=Log.txt
If Exist %LogFile% Del %LogFile%
For /f %%a in ('Type %IP_File%') Do ( 
    echo TTL for "%%a" is : & Call:VBS "%%a"
    ( echo TTL for "%%a" is : & Call:VBS "%%a" )>> %LogFile%
)
echo.
color 0A
echo Hit any key to open the LogFile "%LogFile%"
pause>nul
Start "" %LogFile%
Exit /b

:VBS 
(
    echo wscript.echo TTL(WScript.Arguments(0^)^)
    echo '**********************************************************************************************************
    echo Function TTL(strHost^)
    echo     dim objPing, objRetStatus
    echo     set objPing = GetObject("winmgmts:{impersonationLevel=impersonate}"^).ExecQuery _
    echo       ("select * from Win32_PingStatus where address = '" ^& strHost ^& "'"^)
    echo     for each objRetStatus in objPing
    echo         if IsNull(objRetStatus.StatusCode^) or objRetStatus.StatusCode ^<^> 0 then
    echo            Ping = False
    echo           WScript.Echo "Status code is " ^& objRetStatus.StatusCode
    echo        else
    echo            Ping = True
    echo            TTL = objRetStatus.ResponseTimeToLive 
    echo        end if
    echo     next
    echo End Function 
    echo '**********************************************************************************************************
)> "%vbsfile%"
Cscript /Nologo "%vbsfile%" "%~1"
Exit /b

And i got as output result like that : 我得到的输出结果是这样的:

 TTL for "4.2.2.2" is : 53 TTL for "www.google.com" is : 51 TTL for "www.google.fr" is : 51 TTL for "www.facebook.com" is : 81 TTL for "www.stackoverflow.com" is : 53 TTL for "www.yahoo.com" is : 48 TTL for "www.yahoo.fr" is : 48 TTL for "www.developpez.net" is : 48 

So, my answer seems to turn to a somewhat different one than I was seeking. 因此,我的答案似乎与我寻求的答案有所不同。 It is in python 2.x I just finished writing. 它在python 2.x中,我刚写完。 Although it is not very sophisticated and stealth in terms of execution (pops up lots of CMD windows and writes to files and then reads to form the result). 尽管它不是很复杂并且在执行方面很隐蔽(弹出许多CMD窗口并写入文件,然后读取以形成结果)。 But still got the job done. 但是仍然完成了工作。 I guess I'll have to do more research on DOS commands and start learning VB Scripting ;). 我想我将不得不对DOS命令进行更多研究并开始学习VB脚本;)。 lol. 大声笑。
Thank you @RGuggisberg and @Hackoo for the support 谢谢@RGuggisberg和@Hackoo的支持

import os
import re
cwd = os.getcwd()
ip_file = cwd+"\\ip.txt"     ## IPs written in this file, one in each line, or the filename can be taken through command-line args (more portable)
ip = []
win_hosts = []
for line in open(ip_file).readlines():
    ip.append(line.rstrip())
del_cmd = "del "+cwd+"\\response.txt"    ## Delete response.txt file
os.system(del_cmd)                       ## as PING output keeps appending to it
for i in ip:
    cmd = "ping -n 1 "+str(i)+' | find "TTL" >> response.txt'    ## write PING response to response.txt
    os.system(cmd)
response_file = cwd+"\\response.txt"
for line in open(response_file).readlines():
    regs = r'Reply from\s(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*TTL=(\d{1,3})'   ## Regular Expression to catch IP and TTL-value
    obj = re.search(regs,line.rstrip('\n'))  ## also right-strip any possible new-lines, it'll probably be '\r\n' on Linux host
    if obj:
        ip = obj.group(1)
        ttl = obj.group(2)
        print ip," has TTL= ",ttl
        ttl = int(ttl)
        if (127<ttl<129):                ## change this to (54<ttl<65) to get Linux hosts
            win_hosts.append(ip)         ## Add the windows hosts to win_hosts list
print "\n[+][+] Windows Hosts = ",str(win_hosts)

My ip.txt file has:- 我的ip.txt文件具有:-

192.168.1.1
192.168.1.2
192.168.1.4
192.168.1.5

The result is:- 其结果是:-

>>> 
192.168.1.1  has TTL=  30
192.168.1.2  has TTL=  64
192.168.1.4  has TTL=  64
192.168.1.5  has TTL=  128

[+][+] Windows Hosts =  ['192.168.1.5']

I don't exactly remember but couldn't get support of commands module (not supported on Windows) and subprocess module ( Though they work flawlessly on Linux box ). 我不完全记得,但是无法获得命令模块 (在Windows上不支持)和子进程模块尽管它们在Linux机器上可以正常工作 )的支持。 If someone has any idea on how to store their result to any list/dictionary/variable, plz update. 如果有人对如何将结果存储到任何列表/字典/变量有任何想法,请更新。 I didn't like using output re-directions in CMD. 我不喜欢在CMD中使用输出重定向。

Give a try for this batch file to get the TTL value in the same line having IP address 尝试此批处理文件以在具有IP地址的同一行中获取TTL

@echo off
Title Get TTL from IP adress
set vbsfile=%Tmp%\%~n0.vbs
set IP_File=E:\vb-ping\ip.txt
set LogFile=Log.txt
If Exist %LogFile% Del %LogFile%
For /f %%a in ('Type %IP_File%') Do ( 
     Call:VBS "%%a" & echo  %%a
    ( Call:VBS "%%a" & echo  %%a)>> %LogFile%
)
echo.
color 0A
echo Hit any key to open the LogFile "%LogFile%"
pause>nul
Start "" %LogFile%
Exit /b

:VBS 
(
    echo WScript.StdOut.Write TTL(WScript.Arguments(0^)^)
    echo '**********************************************************************************************************
    echo Function TTL(strHost^)
    echo     dim objPing, objRetStatus
    echo     set objPing = GetObject("winmgmts:{impersonationLevel=impersonate}"^).ExecQuery _
    echo       ("select * from Win32_PingStatus where address = '" ^& strHost ^& "'"^)
    echo     for each objRetStatus in objPing
    echo         if IsNull(objRetStatus.StatusCode^) or objRetStatus.StatusCode ^<^> 0 then
    echo            Ping = False
    echo           WScript.Echo "Status code is " ^& objRetStatus.StatusCode
    echo        else
    echo            Ping = True
    echo            TTL = objRetStatus.ResponseTimeToLive 
    echo        end if
    echo     next
    echo End Function 
    echo '**********************************************************************************************************
)> "%vbsfile%"
Cscript /Nologo "%vbsfile%" "%~1"
Exit /b

So, I created the full scanning script for all the Windows clients which are not a part of my Org's Domain. 因此,我为所有Windows客户端(不是Org的域的一部分)创建了完整的扫描脚本。 It's been enough long time, but I thought to post it here. 时间已经足够长了,但我想在这里发布。

This script relies on initial client's scan with ping-sweep of nmap . 该脚本依赖于使用nmap的 ping-sweep进行的初始客户端扫描。 Since creating script using multiprocessing module didn't work on windows box, so the best shot was nmap . 由于使用多重处理模块创建脚本无法在Windows Box上运行,因此最好的镜头是nmap NMAP does a ping-sweep of full subnet of 255 hosts within few seconds and returns the FQDN (Fully qualified domain names) of the clients found alive in the network. NMAP在几秒钟内对255个主机的完整子网进行ping扫描,并返回在网络中发现的客户端的FQDN(完全限定域名)。

NOTE: you should hve the DNS server defined in your scanner PC. 注意:您应该拥有在扫描仪PC中定义的DNS服务器。

Next thing the script does is, /ites the nmap scan's output to a file nmap_op.txt . 脚本要做的下一件事是,将nmap扫描的输出/ item到文件nmap_op.txt中 Then scripts reads the output from this file and uses regular-expression to take out IP and FQDN. 然后脚本从该文件读取输出,并使用正则表达式取出IP和FQDN。 If any IP isn't having FQDN, it is pinged once and output is written to a file response.txt . 如果任何IP没有FQDN,则对其执行ping操作一次,然后将输出写入到文件response.txt中 This file is read and IPs having TTL value between 100-129 are taken out. 读取该文件,并取出TTL值在100-129之间的IP。

add_to_db function is responsible for returning a list of IP which actually do not belong to Domain. add_to_db函数负责返回实际上不属于域的IP列表。 This function crosschecks the IPs with 3 lists and removes the IP from final list which was in the database file but later was joined to Domain and also keeps adding new non-domain IPs to DB as and when they come online. 此功能对具有3个列表的IP进行交叉检查,并将IP从数据库文件中的最终列表中删除,但后来又加入了Domain,并且在它们联机时也不断向DB添加新的非域IP。

Save this python file in a directory where the script could be able to write files. 将此python文件保存在脚本可以写入文件的目录中。 You should look for two files non-domain-ips.txt (all non domain IPs) and [subnet_value]-result.txt for the final results. 您应该查找两个文件non-domain-ips.txt (所有非域IP)和[subnet_value] -result.txt以获取最终结果。

Usage - run this file in command prompt as follows:- 用法 -在命令提示符下运行此文件,如下所示:
python scanner.py 192.168.1.0/24 192.168.2.0/24 python scan.py 192.168.1.0/24 192.168.2.0/24
You can add any number of networks to scan. 您可以添加任意数量的网络进行扫描。 Plz do not change the pattern of network arg. 请不要更改网络arg的模式。 You must use "/" only to define the mask value of network (do not use * in place of /). 您只能使用“ /”来定义网络的掩码值(不要使用*代替/)。 There is no exception handling on the arguments being passed. 传递的参数没有异常处理。 Rest of the output will be understood when you run the script. 运行脚本时将理解其余的输出。

Further I am thinking to add one or two more functions to define some IPs as exception as per the Vendor's bits of their MAC-Address. 此外,我正在考虑添加一个或两个以上功能,以根据其MAC地址的供应商位将某些IP定义为例外。 For example- some thin-client type devices (as they are going to run in standalone mode only) which give the TTL value of windows range. 例如,某些瘦客户机类型的设备(因为它们将仅在独立模式下运行),它们提供了Windows范围的TTL值。
The script was made in quite a hurry without any use of classes (moreover I'm not very fond of them), so it's in it's ugliest form ;) 脚本是匆忙编写的,没有使用任何类(而且我不太喜欢它们),所以它的形式最丑陋;)

import os
import time
import re
import sys
import pickle
import commands
import subprocess

def add_to_db(nondomain_ips, pickled_ips, domainIPs):
    print "NON domain IPs= ", str(nondomain_ips)
    #raw_input("....")
    print "PICKLED IPs= ",str(pickled_ips)
    #raw_input("....")
    print "Length of PICKLED IPs= ",len(pickled_ips)
    print "domain IPs:- ",str(domainIPs)
    #raw_input("....")
    if (len(pickled_ips) == 0):
        pickled_ips= nondomain_ips
        return pickled_ips
    for new_ip in nondomain_ips:
        print "comparing- ",str(new_ip)
        if new_ip not in pickled_ips:
            print "APPENDING ",str(new_ip),"  to PICKLED IPs"
            pickled_ips.append(new_ip)           
        else:   pass
    for pickled_ip in pickled_ips:
        #print "CHECKING - ",pickled_ip," in domain and in DB file or not"
        if pickled_ip in domainIPs:
            print pickled_ip," JOINED domain, removing from DB file"
            pickled_ips.remove(pickled_ip)
    #print "PICKLED IPs:- ",str(pickled_ips)
    #raw_input("...")
    return pickled_ips
def main():
    if (len(sys.argv)<2):
        print "Wrong args, Give the subnet to scan, Example- \n\npython script.py 192.168.1.0/24 192.168.2.0/24 [more subnets...]\n\nExiting...\n"
        exit(3)
    print "TOTAL SUBNETS TO SCAN:- ",len(sys.argv)
    cwd = os.getcwd()
    print "Current Directory= ",cwd
    outfile = cwd+"\\nmap_op.txt"
    for i in range(1,len(sys.argv)):
    time_now = time.ctime()
        net = sys.argv[i]
        #print i
        #cmd = "nmap -sn " + str(sys.argv[i]) + " -oG "+str(outfile)
        cmd = "nmap -sn " + str(net) + " -oG "+str(outfile)
        print cmd
        try:
            os.remove(outfile)
        except Exception, e:
            print "Error deleting file",str(e)
        #raw_input("SENDING -sn SCAN....\n")
        print "SENDING -sn SCAN....\n"
        os.system(cmd)

        #print "Argv[i]= ",sys.argv[i].split('/')[0]
        print "Argv[i]= ",net.split('/')[0]
        result_file = str(cwd)+"\\"+net.split('/')[0]+"-result.txt"
        print "result file= ",result_file
        #raw_input(" ... ")
        if os.path.exists(outfile):
            print outfile," - oG file created\n\n-------------------------------------\n"
        fp = open(outfile)
        hostlist=[]
        domainIPs = []
        nondomain = []
        ping_file = cwd+"\\response.txt"
        try:
            os.remove(ping_file)
        except Exception, e:
            e=e
        for line in fp.readlines():
            #print line
            #reg = r'Host:(.*\)).*Status.*Up'
            reg = r'Host:\s(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s(\(.*\)).*Status.*Up'
            res = re.match(reg,line)
            if res:
                #print "\t\t",res.group()
                ip = res.group(1)
                if ('()' in res.group(2)):
                    name = 0
                    nondomain.append([ip,name])
                    ping_cmd = 'ping -n 1 '+str(ip)+'| find "TTL" >>'+cwd+"\\response.txt"
                    os.system(ping_cmd)
                else:
                    name = res.group(2)
                    domainIPs.append(ip)
                hostlist.append([ip,name])
            else:   pass #print "No object"
        fp.close()      ## CLOSE THE NMAP OUTPUT FILE-HANDLE
        print "[+][+] All HOSTS:- ",str(hostlist),"\n"
        #print "domain IPs:- ",str(domainIPs)
        print "TOTAL unresolved IPs:- ",nondomain,"\n"
        nondomain_ip = []
        #print "\n\nIP and TTL from RegExp\n"
        regs = r'Reply from\s(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*TTL=(\d{1,3})'
        for line in open(ping_file).readlines():
            #print line
            obj = re.search(regs,line)
            if obj:
                ip = obj.group(1)
                ttl = obj.group(2)
                print str(ip)+" --- " + str(ttl)
                if (100<int(ttl)<129):
                    nondomain_ip.append(ip)
        #print "non domain IPs = ",str(nondomain_ip)
        fp_result = open(result_file,'a')
        fp_result.write("\n\n"+time_now+"\n")
        fp_result.write(str(nondomain_ip))
        fp_result.close()

        db_file = cwd+"\\dbfile"
        if not os.path.exists(db_file):
            fpdb = open(db_file,'w')
            fpdb.close()
            if os.path.exists(db_file):
                print "DB_FILE created"
        with open(db_file,'rb') as fpdb:
            try:
                pickled_ips = pickle.load(fpdb)
            except Exception, error:
                print "Error in loading pickeled list"
                pickled_ips = []
                print "Formed new pickled list= ",str(pickled_ips)
        fpdb.close()
        new_list = add_to_db(nondomain_ip, pickled_ips, domainIPs)
        #print "\nNEW IP-ADDRESSES ESTABLISHED AFTER COMPARING ALL LISTS:- \n",str(new_list)
        with open(db_file, 'wb') as fpdb:
            pickle.dump(new_list, fpdb)
        fpdb.close()
        with open(db_file, 'rb') as fpdb:
            ips = pickle.load(fpdb)
            print "\n\n\t\tTHE NON-domain IPs:- \n",str(ips)
            with open("non-domain-ips.txt",'wb') as handle:
                for ip in ips:
                    handle.write(ip)
                    handle.write("\r\n")
            handle.close()
        print "SLEEPING FOR 10 SECONDS..."
        time.sleep(10)
if __name__ == '__main__':
    while True:
        main()
        print "\n\n\n\t\tSCAN COMPLETED...sleep for 5 minutes before running another loop of scan...\n\n\n"
        time.sleep(300)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM