Lưu ý cho người đọc : Câu trả lời ban đầu đã được đăng cách đây một thời gian và tại thời điểm tôi chỉ học kịch bản shell. Xem phiên bản được xem lại dưới đây để biết một kịch bản mới và được cải thiện, hoạt động nhanh hơn nhiều.
Câu trả lời gốc
nmap
sẽ là lựa chọn số 1 của tôi, nhưng nếu bạn không có nó thì sao? Cách DIY sẽ là với một tập lệnh ping đi qua từng địa chỉ IP có thể có trên mạng theo cách thủ công. Những gì chúng ta có ở đây chỉ là vòng lặp while, nơi chúng ta đặt số cuối cùng trong địa chỉ, tạo một ping đơn lẻ thành địa chỉ, kiểm tra xem lệnh có thành công hay không (và nếu nó đã thành công, thì máy chủ rõ ràng đã lên) và printf
tuyên bố. Cách nhanh và bẩn, tôi mất khoảng 10 phút để viết nó, nhưng thời gian chạy có thể hơi chậm.
#!/bin/sh
# set -x
NUM=1
while [ $NUM -lt 256 ];do
ping -q -c 1 192.168.0.$NUM > /dev/null
RESULT=$(echo $?)
if [ $RESULT -eq 0 ]; then
printf 192.168.0.$NUM"\n"
fi
NUM=$(expr $NUM + 1)
done
Trả lời lại
Ban đầu tôi đã đăng câu trả lời này vào tháng 8 năm 2015. Kể từ đó tôi đã tìm hiểu thêm một chút về kịch bản shell, và một khi tôi đã xem kịch bản này, tôi nghĩ sẽ là một ý tưởng tốt để xem lại câu trả lời này để thêm một vài cải tiến. Dưới đây là một vài ý tưởng:
Kịch bản rõ ràng là chậm và ping
chờ phản hồi từ chủ nhà. Theo mặc định, ping
đối với hai RTT, có thể thay đổi tùy thuộc vào mức độ tắc nghẽn của mạng của bạn và theo như tôi hiểu giao thức TCP nhân đôi thời gian chờ mỗi lần (ít nhất là theo điều này ). Vì vậy, chúng tôi có thể buộc ping
phải hết thời gian với -w 1
cờ. Vì chúng tôi có 256 địa chỉ và chúng tôi giả sử 1 giây cho mỗi địa chỉ, tập lệnh sẽ mất khoảng 256/60 = 4,27 phút.
Thực hiện một lệnh và sau đó nắm bắt trạng thái thoát của nó $?
là không thực sự cần thiết. Có if ... then;...fi
thể hoạt động trên các lệnh trực tiếp. Nói cách khác, nó đủ để làm điều này:
if ping -w 1 -q -c 1 192.168.0.$NUM > /dev/null ;
then
<some other code here>
fi
Các printf
lệnh có thể được viết lại như vậy:
printf "IP %s is up\n" 192.168.0."$NUM"
Đây là một sự thay đổi về phong cách, nhưng nó phù hợp với cách printf
hoạt động và trông giống như trong nhiều ngôn ngữ khác, với "$NUM"
biến trích dẫn . Trích dẫn ở đây là không cần thiết - vì chúng tôi chỉ xử lý các số, chúng tôi không cần phải dự đoán việc chia từ do có khoảng trắng trong một biến.
Cải thiện hiệu suất tốt hơn nhiều có thể đạt được nếu chúng ta sinh ra một số quy trình nền. Các kịch bản chỉnh sửa dưới đây thực hiện chính xác điều đó. Tôi đặt ping
và printf
vào một chức năng, pingf
(vâng, tên Corny, tôi biết). Bây giờ, cũng có một main
chức năng duy nhất thực hiện vòng lặp và gọi pingf
.
#!/bin/sh
# Uncomment for debugging
#set -x
pingf(){
if ping -w 2 -q -c 1 192.168.0."$1" > /dev/null ;
then
printf "IP %s is up\n" 192.168.0."$1"
fi
}
main(){
NUM=1
while [ $NUM -lt 255 ];do
pingf "$NUM" &
NUM=$(expr "$NUM" + 1)
done
wait
}
main
Làm thế nào tốt hơn làm việc đó? Không tệ, thực sự, mất một vài giây.
$ time ./ping_script.sh
IP 192.168.0.1 is up
IP 192.168.0.101 is up
IP 192.168.0.27 is up
IP 192.168.0.29 is up
0m02.50s real 0m00.01s user 0m00.12s system
Những điều cần lưu ý
- Windows (bắt đầu từ Windows 7, tôi nghĩ) đã bắt đầu chặn phản hồi đối với các yêu cầu tiếng vang ICMP. Có khá nhiều câu hỏi về vấn đề đó trên Ask Ubuntu và các trang web khác thuộc loại "Này, máy tính Linux của tôi có thể được ping, nhưng không phải là Windows, có chuyện gì vậy?" Chỉ cần lưu ý rằng thực tế là đối với các phiên bản Windows mới hơn, bạn cần phải kích hoạt phản hồi cho tiếng vang ICMP.
angry ip scanner