Am'm în căutarea pentru o metodă rapidă și simplă pentru testarea în mod corespunzător dacă un anumit port TCP este deschis pe un server de la distanță, din interiorul unui script de Shell.
Am'am reusit sa fac cu comanda telnet, și funcționează bine atunci când portul este deschis, dar nu't par să timeout atunci când l's nu-și atârnă acolo...
Aici's o mostră:
l_TELNET=`echo "quit" | telnet $SERVER $PORT | grep "Escape character is"`
if [ "$?" -ne 0 ]; then
echo "Connection to $SERVER on port $PORT failed"
exit 1
else
echo "Connection to $SERVER on port $PORT succeeded"
exit 0
fi
Am nevoie ori de o modalitate mai bună, sau o modalitate de a forța telnet la expirare, dacă nu't conectați în sub 8 secunde, de exemplu, și să se întoarcă ceva ce poate prinde în Coajă (cod retur, sau șir în stdout).
Știu de Perl metodă, care utilizează IO::Soclu::INET module și a scris un succes script care testează un port, dar ar dori mai degrabă pentru a evita folosind Perl, dacă este posibil.
Notă: Aceasta este ce serverul se execută (în cazul în care am nevoie pentru a rula acest de)
SunOS 5.10 Generic_139556-08 i86pc i386 i86pc
Așa cum sa arătat de către B. Rodos, nc
va face treaba. O mai compact mod de a folosi:
nc -z <host> <port>
Așa " nc " va verifica daca portul este deschis, ieșirea cu 0 la succes, 1 în caz de eșec.
Pentru o rapidă interactive de verificare (cu 5 secunde timeout):
nc -z -v -w5 <host> <port>
L's destul de ușor de a face cu -z " și "- w TIMEOUT
opțiuni pentru a nc
, dar nu toate sistemele au " nc " instalat. Dacă aveți o destul de recentă versiune de bash, acest lucru va funcționa:
# Connection successful:
$ timeout 1 bash -c 'cat < /dev/null > /dev/tcp/google.com/80'
$ echo $?
0
# Connection failure prior to the timeout
$ timeout 1 bash -c 'cat < /dev/null > /dev/tcp/sfsfdfdff.com/80'
bash: sfsfdfdff.com: Name or service not known
bash: /dev/tcp/sfsfdfdff.com/80: Invalid argument
$ echo $?
1
# Connection not established by the timeout
$ timeout 1 bash -c 'cat < /dev/null > /dev/tcp/google.com/81'
$ echo $?
124
Ce's a întâmplat aici este că "timeout" va rula subcomanda și ucide-l, dacă nu't de ieșire în timeout specificat (1 secundă în exemplul de mai sus). În acest caz bash
este subcomanda și utilizările sale speciale /dev/tcp manipularea pentru a încerca și de a deschide o conexiune cu serverul și portul specificat. Dacă bash
poate deschide o conexiune în termen de expirare, " cat "va închide imediat (din it's de lectură de la/dev/null) și de ieșire cu un cod de stare de "0", care se va propaga prin
bashși apoi "timeout". Dacă
bashdevine o eroare de conectare înainte de a specificat timeout, atunci
bashva ieși cu un cod de ieșire de 1 care "timeout" va reveni, de asemenea,. Și dacă bash e't se poate stabili o conexiune și timeout specificat expiră, apoi "timeout" va ucide
bash` și ieși cu o stare de 124.
Rețineți că "timeout" ar trebui să fie prezente cu RHEL 6+, sau, alternativ, a fost găsit în GNU coreutils 8.22. Pe MacOS, instalați-l folosind o fiertură de a instala coreutilsși de a folosi ca
gtimeout`.
$ timeout $TIMEOUT_SECONDS bash -c "</dev/tcp/${HOST}/${PORT}"; echo $?
Dacă parametrizing gazdă și port, asigurați-vă că pentru a le preciza ca ${GAZDĂ} " și " ${PORTUL}
ca este mai sus. Nu le specifica doar ca $HOST " și " $PORT
, adică fără bretele; nu va't de lucru în acest caz.
$ timeout 2 bash -c "</dev/tcp/canyouseeme.org/80"; echo $?
0
$ timeout 2 bash -c "</dev/tcp/canyouseeme.org/81"; echo $?
124
Dacă trebuie să păstreze starea de ieșire de bash
,
$ timeout --preserve-status 2 bash -c "</dev/tcp/canyouseeme.org/81"; echo $?
143
Rețineți că o înapoi versiune incompatibilă de " nc " devine instalat pe RHEL 7.
Rețineți că comanda de mai jos este unic în faptul că acesta este identic pentru ambele RHEL 6 și 7. L's doar instalarea și de ieșire care sunt diferite.
$ nc -w $TIMEOUT_SECONDS -v $HOST $PORT </dev/null; echo $?
$ sudo yum install nc
$ nc -w 2 -v canyouseeme.org 80 </dev/null; echo $?
Connection to canyouseeme.org 80 port [tcp/http] succeeded!
0
$ nc -w 2 -v canyouseeme.org 81 </dev/null; echo $?
nc: connect to canyouseeme.org port 81 (tcp) timed out: Operation now in progress
1
Dacă numele de gazdă hărți pentru mai multe ip-uri, cele de mai sus faptul că nu comanda va parcurge mai multe sau toate dintre ele. De exemplu:
$ nc -w 2 -v microsoft.com 81 </dev/null; echo $?
nc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progress
nc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progress
nc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progress
nc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progress
nc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progress
1
$ sudo yum install nmap-ncat
$ nc -w 2 -v canyouseeme.org 80 </dev/null; echo $?
Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Connected to 52.202.215.126:80.
Ncat: 0 bytes sent, 0 bytes received in 0.22 seconds.
0
$ nc -w 2 -v canyouseeme.org 81 </dev/null; echo $?
Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Connection timed out.
1
Dacă numele de gazdă hărți pentru mai multe ip-uri, cele de mai sus faptul că nu comanda va parcurge mai multe sau toate dintre ele. De exemplu:
$ nc -w 2 -v microsoft.com 81 </dev/null; echo $?
Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Connection to 104.43.195.251 failed: Connection timed out.
Ncat: Trying next address...
Ncat: Connection to 23.100.122.175 failed: Connection timed out.
Ncat: Trying next address...
Ncat: Connection to 23.96.52.53 failed: Connection timed out.
Ncat: Trying next address...
Ncat: Connection to 191.239.213.197 failed: Connection timed out.
Ncat: Trying next address...
Ncat: Connection timed out.
1
A -v
(--verbose
) argument și echo $?
comanda sunt, desigur, doar pentru ilustrare.
Cu netcat poti verifica daca portul este deschis astfel:
nc my.example.com 80 < /dev/null
Valoarea de returnare a nc
va fi de succes dacă portul TCP a fost deschis, și eșecul (de obicei codul return 1) dacă nu a putut face conexiunea TCP.
Unele versiuni ale " nc " va închide atunci când încercați acest lucru, deoarece nu au aproape trimiterea jumătate din priză chiar și după primirea end-of-file din /dev/null
. Pe propria mea Ubuntu laptop (18.04), la netcat-openbsd
versiune de netcat pe care am instalat oferă o soluție: a -N
opțiune este necesară pentru a obține un rezultat imediat:
nc -N my.example.com 80 < /dev/null
În Bash folosind pseudo-dispozitiv de fișiere pentru TCP/UDP conexiuni este drept înainte. Aici este scriptul:
#!/usr/bin/env bash
SERVER=example.com
PORT=80
</dev/tcp/$SERVER/$PORT
if [ "$?" -ne 0 ]; then
echo "Connection to $SERVER on port $PORT failed"
exit 1
else
echo "Connection to $SERVER on port $PORT succeeded"
exit 0
fi
Testare:
$ ./test.sh
Connection to example.com on port 80 succeeded
Aici este o linie (Bash sintaxa):
</dev/tcp/localhost/11211 && echo Port open. || echo Port closed.
Rețineți că unele servere pot fi protejate de firewall SYN atacuri, astfel încât să aveți o conexiune TCP timeout (~75secs). Pentru a rezolva problema timeout problema, încercați:
timeout 1 bash -c "</dev/tcp/stackoverflow.com/81" && echo Port open. || echo Port closed.
A se vedea: https://stackoverflow.com/q/24317341/55075
Aveam nevoie și de o soluție flexibilă pentru a lucra pe mai multe arhive git asa ca am scris următoarele sh cod bazat pe 1 și 2. Puteți folosi o adresă de server în loc de gitlab.com și port în a înlocui de 22 de ani.
SERVER=gitlab.com
PORT=22
nc -z -v -w5 $SERVER $PORT
result1=$?
#Do whatever you want
if [ "$result1" != 0 ]; then
echo 'port 22 is closed'
else
echo 'port 22 is open'
fi
Daca're folosind ksh sau bash ambele au suport IO redirecționare de la/la o priză utilizând /dev/tcp/IP/PORT construct. În acest Korn shell exemplu sunt redirecționarea nu-op's (:) std-in de la o priză:
W$ python -m SimpleHTTPServer &
[1] 16833
Serving HTTP on 0.0.0.0 port 8000 ...
W$ : </dev/tcp/127.0.0.1/8000
Coajă imprimă o eroare în cazul în care priza nu este deschis:
W$ : </dev/tcp/127.0.0.1/8001
ksh: /dev/tcp/127.0.0.1/8001: cannot open [Connection refused]
Prin urmare, puteți folosi acest lucru ca test o daca condiție:
SERVER=127.0.0.1 PORT=8000
if (: < /dev/tcp/$SERVER/$PORT) 2>/dev/null
then
print succeeded
else
print failed
fi
Nu-op este într-un subshell așa că am putea arunca std-err departe dacă std-în redirection nu reușește.
Eu folosesc de multe ori /dev/tcp pentru a verifica disponibilitatea unei resurse pe HTTP:
W$ print arghhh > grr.html
W$ python -m SimpleHTTPServer &
[1] 16863
Serving HTTP on 0.0.0.0 port 8000 ...
W$ (print -u9 'GET /grr.html HTTP/1.0\n';cat <&9) 9<>/dev/tcp/127.0.0.1/8000
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/2.6.1
Date: Thu, 14 Feb 2013 12:56:29 GMT
Content-type: text/html
Content-Length: 7
Last-Modified: Thu, 14 Feb 2013 12:55:44 GMT
arghhh
W$
Acest one-liner deschide file descriptor 9 pentru citire și de scriere la priza, imprimă HTTP GET la priză și utilizează " cat " pentru a citi de la priza.
În timp ce o întrebare veche, am'am avut de-a face cu o variantă de ea, dar nici una dintre solutiile de aici au fost aplicabile, așa că am găsit un alt, și sunt adăugarea-l pentru posteritate. Da, știu OP declarat că au fost conștienți de această opțiune și nu't-i se potriveste, ci pentru oricine, urmând apoi s-ar putea dovedi utile.
În cazul meu, vreau să-test pentru disponibilitatea de un local de apt-cacher-ng
servicii de la un dockerconstrui. Asta înseamnă că absolut nimic nu poate fi instalat înainte de încercare. Nu
nc,
nmap,
aștept,
telnet " sau " python.
perl` cu toate acestea este prezent, împreună cu bibliotecile de bază, așa că am folosit asta:
perl -MIO::Socket::INET -e 'exit(! defined( IO::Socket::INET->new("172.17.42.1:3142")))'
În unele cazuri, în cazul în care instrumente, cum ar fi curl, telnet, nc o nmap nu sunt disponibile încă mai ai o șansă cu wget
if [[ $(wget -q -t 1 --spider --dns-timeout 3 --connect-timeout 10 host:port; echo $?) -eq 0 ]]; then echo "OK"; else echo "FAIL"; fi
Dacă doriți să utilizați " nc " dar nu't au o versiune care sprijin -z
, încercați să utilizați ` ... trimite-doar pentru:
nc --send-only <IP> <PORT> </dev/null
și cu timeout:
nc -w 1 --send-only <IP> <PORT> </dev/null
și fără a DNS lookup daca's IP:
nc -n -w 1 --send-only <IP> <PORT> </dev/null
Se întoarce coduri ca -z
, bazat pe dacă se poate conecta sau nu.
Am'm ghicitul că-l's prea tarziu pentru un raspuns, iar acest lucru nu ar putea fi unul bun, dar aici te duci...
Ce zici de a pune-l în interiorul de o buclă în timp ce, cu un cronometru de un anumit fel. Am'm mai mult de o Perl tip decât Solaris, dar în funcție de shell're folosind, ar trebui să fie capabil să facă ceva de genul:
TIME = 'date +%s' + 15
while TIME != `date +%s'
do whatever
Și apoi doar să adăugați un steag în buclă în timp ce, așa că, dacă-l ori înainte de finalizare, puteți cita timeout ca motivul pentru eșec.
Bănuiesc că telnet are un timp de expirare a comuta la fel de bine, dar doar pe partea de sus a capul meu, cred că cele de mai sus va funcționa.
Am nevoie de script scurt, care a fost condusă în cron și n't de ieșire. Am să-mi rezolve probleme folosind nmap
open=`nmap -p $PORT $SERVER | grep "$PORT" | grep open`
if [ -z "$open" ]; then
echo "Connection to $SERVER on port $PORT failed"
exit 1
else
echo "Connection to $SERVER on port $PORT succeeded"
exit 0
fi
Pentru a rula aceasta ar trebui să instalați nmap pentru că nu este instalat implicit pachet.
Aceasta foloseste telnet în spatele scenei, și pare să funcționeze bine pe mac/linux. Nu't folosi netcat pentru că diferențele între versiunile pe linux/mac, și acest lucru funcționează cu un default mac instala.
$ is_port_open.sh 80 google.com
OPEN
$ is_port_open.sh 8080 google.com
CLOSED
PORT=$1
HOST=$2
TIMEOUT_IN_SEC=${3:-1}
VALUE_IF_OPEN=${4:-"OPEN"}
VALUE_IF_CLOSED=${5:-"CLOSED"}
function eztern()
{
if [ "$1" == "$2" ]
then
echo $3
else
echo $4
fi
}
# cross platform timeout util to support mac mostly
# https://gist.github.com/jaytaylor/6527607
function eztimeout() { perl -e 'alarm shift; exec @ARGV' "$@"; }
function testPort()
{
OPTS=""
# find out if port is open using telnet
# by saving telnet output to temporary file
# and looking for "Escape character" response
# from telnet
FILENAME="/tmp/__port_check_$(uuidgen)"
RESULT=$(eztimeout $TIMEOUT_IN_SEC telnet $HOST $PORT &> $FILENAME; cat $FILENAME | tail -n1)
rm -f $FILENAME;
SUCCESS=$(eztern "$RESULT" "Escape character is '^]'." "$VALUE_IF_OPEN" "$VALUE_IF_CLOSED")
echo "$SUCCESS"
}
testPort
Clădirea de pe cel mai înalt votat răspunsul, aici este o funcție să aștepte două porturi să fie deschis, cu o pauză la fel de bine. Notă cele două porturi care mus fi deschis, 8890 și 1111, precum și max_attempts (1 pe secundă).
function wait_for_server_to_boot()
{
echo "Waiting for server to boot up..."
attempts=0
max_attempts=30
while ( nc 127.0.0.1 8890 < /dev/null || nc 127.0.0.1 1111 < /dev/null ) && [[ $attempts < $max_attempts ]] ; do
attempts=$((attempts+1))
sleep 1;
echo "waiting... (${attempts}/${max_attempts})"
done
}