Можно использовать должностное лицо как это наверху сценария:
exec > >(tee "$HOME/somefile.log") 2>&1
Например:
#!/bin/bash -
exec > >(tee "$HOME/somefile.log") 2>&1
echo "$HOME"
echo hi
date
date +%F
echo bye 1>&2
Дает мне вывод файлу $HOME/somefile.log
и к терминалу как это:
/home/saml
hi
Sun Jan 20 13:54:17 EST 2013
2013-01-20
bye
Что-либо в частном пространстве IP будет всегда запускаться с одного из трех блоков IP-адреса.
Таким образом, просто grep для вышеупомянутых типов IP-адресов.
$ ifconfig | grep 'inet addr' | cut -d ':' -f 2 | awk '{ print $1 }' | \
grep -E '^(192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.)'
192.168.1.20
grep
Я использую, использует регулярные выражения. В этом случае мы ищем следующие шаблоны:
Дополнительно мы являемся явными только в соответствии числам, которые запускаются с одного из этих шаблонов. Привязка (^
) предоставляет эту возможность нам.
Если мы добавляем следующие строки к файлу только для тестирования grep
.
$ cat afile
192.168.0.1
10.11.15.3
1.23.3.4
172.16.2.4
Мы можем затем протестировать его как так:
$ cat afile | grep -E '^(192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.)'
192.168.0.1
10.11.15.3
172.16.2.4
IPv4 был создан в то время, когда 32-разрядные системы были распространены. Отмеченный точкой десятичный адрес IPv4 может быть сохранен в 32-разрядное целое число без знака, и битовые операции эффективно выполняются сетевым оборудованием. Битовая маска для 172.16.0.0/12 CIDR может быть сформирована из единственного сдвига влево и проверена по адресу с поразрядным синглом - и.
Существует три 'частных' диапазона сетевого адреса, определенные RFC 1918.
10.x.y.z/8
172.16+x.y.z/12
, где x in [0..15]
192.168.y.z/16
Кроме того, для подразделения сети оператора,
100.64+x.y.z/10
, где x in [0..63]
И для локальных для ссылки адресов,
169.254.y.z/16
С языком, который поддерживает битовые операции, можно преобразовать точечный десятичный адрес в целое число легко,
//assume x[0],x[1],x[2],x[3] are the parts of a dotted ip address
unsigned int ipv4 = (( (( (x[0]<<8) |x[1])<<8) |x[2])<<8) |x[3]
Предположим, что Вы определили константы для вышеупомянутых перечисленных адресов,
CIDR8 = (( (( (10<<8) |0xff)<<8) |0xff)<<8) |0xff
CIDR12 = (( (( (172<<8) |16 |0xf)<<8) |0xff)<<8) |0xff
CIDR16 = (( (( (192<<8) |168)<<8) |0xff)<<8) |0xff
CIDR10 = (( (( (100<<8) |64 |0x3f)<<8) |0xff)<<8) |0xff
CIDRLL = (( (( (169<<8) |254)<<8) |0xff)<<8) |0xff
Проверка, является ли Ваш адрес ipv4 одним из этих адресов, проста,
ipv4 == (ipv4 & CIDR8) //10.0.0.0/8
ipv4 == (ipv4 & CIDR12) //172.16.0.0/12
ipv4 == (ipv4 & CIDR16) //192.168.0.0/16
ipv4 == (ipv4 & CIDR10) //100.64.0.0/10
ipv4 == (ipv4 & CIDRLL) //169.254.0.0/16
Вместо того, чтобы проверять на 16 различных 172.16.0.0/12 сетей, можно использовать вышеупомянутый подход битовой маски к непосредственно проверке, является ли адрес ipv4 частью одной из этих частных сетей (NAT). Выбор жемчуга (Python или рубин также работают), вместо оболочки или awk, и использование поразрядного сингла и операция значительно сокращают работу.
sub isprivate
{
my($inet) = @_;
if( $inet =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/ ) {
if( $1==10 ) { return 10; }
if( $1==172 && (($2 & 0x1f) == $2) ) { return 172; }
if( $1==192 && ($2==168) ) { return 192; }
}
return 0;
};
sub iscarrier
{
my($inet) = @_;
if( $inet =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/ ) {
if( $1==100 && (($2 & 0x7f) == $2) ) { return 100; }
}
return 0;
};
sub islinklocal
{
my($inet) = @_;
if( $inet =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/ ) {
if( $1==169 && ($2==254) ) { return 169; }
}
return 0;
};
Как Вы хотите классифицировать адреса?
sub ipaddr
{
my($inet) = @_;
{
if( isprivate($inet)>0 ) { $kind = "private"; }
elsif( isloop($inet)>0 ) { $kind = "loopback"; }
elsif( iscarrier($inet)>0 ) { $kind = "carrier"; }
elsif( islinklocal($inet)>0 ) { $kind = "linklocal"; }
else { $kind = ""; }
print "$iface: $inet $netmask $broadcast ($flagsdesc) $kind\n";
}
};
Выполненный ifconfig из сценария жемчуга,
$found = 0;
open($fh,"/sbin/ifconfig|");
while($line=<$fh>)
{
chomp($line); $line =~ s/^\s+//;
if( $line =~ /(\w+):\s+flags=(\d+)\s*\<(.*)\>\s+mtu\s+(\d+)\b/ ) {
if( $found ) { ipaddr($inet); }
$found = 1;
($iface,$flags,$flagsdesc,$mtu) = ($1,$2,$3,$4);
}
if( $line =~ /inet\s+(\d+\.\d+\.\d+\.\d+)\b/ ) {
($inet,$netmask,$broadcast) = ($1,"","");
if( $line =~ /netmask\s+([\d+\.]+)\b/ ) { ($netmask) = ($1); }
if( $line =~ /broadcast\s+([\d\.]+)\b/ ) { ($broadcast) = ($1); }
}
}
if( $found ) { ipaddr($inet); }
Вывод (одна строка на IP) может быть фильтрован со следующим сценарием:
#!/bin/sh
PATTERN='^10\.' # 10.0.0.0/8
PATTERN+='|^192\.168\.' # 192.168.0.0/16
PATTERN+='|^169\.254\.' # not strictly private range, but link local
for i in $(seq 16 31) ; do # 172.16.0.0/12
PATTERN+="|^172\.$i\."
done
egrep "$PATTERN"
exit 0
Использование, например:
ifconfig | grep 'inet addr' | cut -d ':' -f 2 | awk '{ print $1 }' | ./filter_private_ips
Показать частные IP-адреса
ip -o addr show | \
grep -v 'inet6' | \
grep -v 'scope host' | \
awk '{print $4}' | \
cut -d '/' -f 1 | \
grep -E '^(192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.)'
Показать общедоступные IP-адреса
ip -o addr show | \
grep -v 'inet6' | \
grep -v 'scope host' | \
awk '{print $4}' | \
cut -d '/' -f 1 | \
grep -vE '^(192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.)'