В разработке программного обеспечения все меняется с невероятной скоростью — в том числе инструменты, которые мы используем. Это происходит в результате совершенствования аппаратной части, инфраструктурных сред. Иногда старые инструменты плохо адаптируются к реалиям, поэтому они в конечном итоге исчезают, и на замену им приходят новые утилиты.

"Все новое — лучше, чем старое" — девиз, который не всегда применим для утилит в Linux. Но все же исключения есть.

В статье под катом разработчик Хосе Висенте Нуньес* рассказывает о нескольких устаревших инструментах, которые вы, возможно, все еще используете. А также о том, чем их можно заменить. Автор объясняет, почему вам следует переключиться на эти улучшенные альтернативы, которые обеспечивают ту же — а в некоторых случаях даже большую — функциональность. Список составлен в произвольном порядке.

*Обращаем ваше внимание, что позиция автора может не всегда совпадать с мнением МойОфис.


egrep и fgrep: используйте взамен этих команд флаги

Уважаемая многими команда grep — один из лучших примеров философии операционной системы Unix:

Пишите программы, которые выполняют одну задачу и делают это хорошо. Пишите программы для совместной работы. Пишите программы, которые бы поддерживали текстовые потоки, поскольку это универсальный интерфейс.

Инструмент egrep (extended grep) использует регулярные выражения для сопоставления строки. Однако egrep устарел, и теперь его имеет смысл заменять обычным grep с флагом grep -E.

Например:

$ egrep '^[fj]' /etc/passwd
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
josevnz:x:1000:1000:josevnz:/home/josevnz:/bin/bash

$ grep -E '^[fj]' /etc/passwd
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
josevnz:x:1000:3000:josevnz:/home/josevnz:/bin/bash

Оба примера выведут соответствующие строки, которые начинаются с буквы j или f в файле /etc/passwd.

Чтобы получить больше примеров, скачайте эту шпаргалку: Linux grep command cheat sheet.

Другой пример, добавление нового флага — fgrep. Команда fixed grep использует фиксированную строку для сопоставления (без оптимизации, поэтому она быстрее, чем регулярное выражение). Утилита fgrep легко заменяется на grep -F.

Посмотрим в сравнении:

$ fgrep 'josevnz' /etc/passwd
josevnz:x:1000:3000:josevnz:/home/josevnz:/bin/bash

$ grep -F 'josevnz' /etc/passwd
josevnz:x:1000:3000:josevnz:/home/josevnz:/bin/bash

Почему egrep и fgrep были заменены?

Для инструмента, обеспечивающего аналогичное поведение, использовать флаги более естественно. Нам нужно знать, что grep с флагом может использовать регулярные выражения или выполнять точный поиск.

nslookup: "I’ll be back"

Введите «Y», если вы когда-либо пытались получить IP-адрес сервера следующим образом:

$ nslookup kodegeek.com
Server:		192.168.1.1
Address:	192.168.1.1#53

Non-authoritative answer:
Name:	kodegeek.com
Address: 50.63.7.206

Альтернативой nslookup является dig. Вот пример, аналогичный приведённому выше:

$ dig @192.168.1.1 kodegeek.com A +noall +answer +nocmd
kodegeek.com.		600	IN	A	50.63.7.206

Еще один пример. Ниже в интерактивном режиме показано, как получить запись указателя (PTR) того же сервера:

> set type=ptr
> 50.63.7.206
Server:		192.168.1.1
Address:	192.168.1.1#53

Non-authoritative answer:
206.7.63.50.in-addr.arpa	name = ip-50-63-7-206.ip.secureserver.net.

Authoritative answers can be found from:

Аналог команды dig выглядит так:

$ dig -x @192.168.1.1 kodegeek.com +noall +answer +nocmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 22696
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;1.1.168.\@192.in-addr.arpa.	IN	PTR

;; AUTHORITY SECTION:
in-addr.arpa.		3549	IN	SOA	b.in-addr-servers.arpa. nstld.iana.org. 2022033331 1800 900 604800 3600

;; Query time: 24 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Tue May 17 05:08:21 EDT 2022
;; MSG SIZE  rcvd: 122

kodegeek.com.		600	IN	A	50.63.7.206

Команда dig может делать то, чего не может nslookup. Например, с ее помощью вы можете запросить передачу доменной зоны в формате файла зоны (включая все типы записей), чтобы сделать резервную копию зоны вашего домена:

$ dig +short ns kodegeek.com
ns51.domaincontrol.com.
ns52.domaincontrol.com.
$ dig axfr kodegeek.com @ns51.domaincontrol.com.
# *Note:* In this case it won't work because kodegeek.com has a domain protection. But the domain in your intranet may work.

Но и nslookup может делать то, чего не может dig, например, дружественный интерактивный режим, который очень полезен при изучении доменных зон DNS. Также nslookup может работать в неинтерактивном режиме.

В чем же разница? Утилита dig использует системные библиотеки операционной системы для разрешения имен (local Domain Name System resolver library), а nslookup — нет. В результате они могут вести себя по-разному при выполнении запросов.

Почему был заменен nslookup?

На самом деле nslookup планировался к выводу, но не был заменен на dig (или host). Обратимся к "Википедии":

nslookup — программное обеспечение сервера имен BIND. В начале... при разработке BIND 9 Internet Systems Consortium (ISC) планировал отказаться от nslookup в пользу host и dig. Это решение было отменено в 2004 году с выпуском BIND 9.3, и с тех пор остается неизменным.

Так что, зная особенности, вполне логично использовать оба инструмента.

ifconfig, netstat, route: попробуйте ip

Вы можете использовать ifconfig для получения информации о сетевых интерфейсах и изменения их настроек.

Например:

$ /sbin/ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:43:f9:d0:b4  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

enp1s0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        ether 00:1f:f3:46:38:96  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        device interrupt 16  

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 30  bytes 1170 (1.1 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 30  bytes 1170 (1.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wls1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.16  netmask 255.255.255.0  broadcast 192.168.1.255
        inet6 fe80::ac00:48ea:c7a6:1488  prefixlen 64  scopeid 0x20<link>
        inet6 fd22:4e39:e630:1:6688:3ffd:ea5b:d9e9  prefixlen 64  scopeid 0x0<global>
        ether 00:23:6c:7b:db:ac  txqueuelen 1000  (Ethernet)
        RX packets 1115786  bytes 107099421 (102.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 548530  bytes 359598134 (342.9 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Однако ifconfig был заменен на ip. Вот как сообщается список сетевых интерфейсов с помощью ip:

$ ip address 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp1s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
    link/ether 00:1f:f3:46:38:96 brd ff:ff:ff:ff:ff:ff
3: wls1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:23:6c:7b:db:ac brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.16/24 brd 192.168.1.255 scope global noprefixroute wls1
       valid_lft forever preferred_lft forever
    inet6 fd22:4e39:e630:1:6688:3ffd:ea5b:d9e9/64 scope global noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 fe80::ac00:48ea:c7a6:1488/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:43:f9:d0:b4 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

Еще один полезный инструмент — route. Используйте следующую команду, чтобы проверить таблицу маршрутизации:

$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG    600    0        0 wls1
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.1.0     0.0.0.0         255.255.255.0   U     600    0        0 wls1

Команда ip также может отображать таблицу маршрутизации. В следующем примере показано, почему этот инструмент взял верх (думаю, помимо прочего, дело в формате его вывода):

$ ip route list
default via 192.168.1.1 dev wls1 proto static metric 600 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
192.168.1.0/24 dev wls1 proto kernel scope link src 192.168.1.16 metric 600

Еще одна утилита, которая была заменена, это netstat. С помощью netstat вы, среди прочего, можете увидеть список активных подключений. Например, чтобы просмотреть список активных TCP-соединений (listening) на вашем сервере без разрешения имен, введите:

$ /usr/bin/netstat --numeric --tcp --listen
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 192.168.122.1:53        0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:5355            0.0.0.0:*               LISTEN     
tcp6       0      0 :::22                   :::*                    LISTEN     
tcp6       0      0 ::1:631                 :::*                    LISTEN     
tcp6       0      0 :::9323                 :::*                    LISTEN     
tcp6       0      0 :::5355                 :::*                    LISTEN     
tcp6       0      0 :::9100                 :::*                    LISTEN    

В этом случае заменой является команда ss:

$ ss --numeric --tcp --listen
State               Recv-Q               Send-Q                             Local Address:Port                             Peer Address:Port              Process              
LISTEN              0                    32                                 192.168.122.1:53                                    0.0.0.0:*
LISTEN              0                    4096                               127.0.0.53%lo:53                                    0.0.0.0:*
LISTEN              0                    128                                      0.0.0.0:22                                    0.0.0.0:*
LISTEN              0                    128                                    127.0.0.1:631                                   0.0.0.0:*
LISTEN              0                    4096                                     0.0.0.0:5355                                  0.0.0.0:*
LISTEN              0                    128                                         [::]:22                                       [::]:*
LISTEN              0                    128                                        [::1]:631                                      [::]:*
LISTEN              0                    4096                                           *:9323                                        *:*
LISTEN              0                    4096                                        [::]:5355                                     [::]:*
LISTEN              0                    4096                                           *:9100                                        *:*

Почему ifconfig, route и netstat устарели?

Отсутствие технического сопровождения стало причиной вывода этих инструментов. Согласно той же "Википедии", их место заняли более новые утилиты:

Многие дистрибутивы Linux (например, ArchLinux, RHEL 7 и выше) отказались от использования ifconfig и route в пользу программного пакета iproute2, который включает поддержку всех общих функций ifconfig(8), route(8), arp(8) и netstat(1). Он также включает в себя поддержку multicast-конфигурации, управление туннелями и виртуальными ссылками, контроль трафика, низкоуровневую настройку IPsec и другие функции.

Подводим итоги

  • Важно следить за новейшими инструментами, поскольку разработчики исправляют ошибки и добавляют полезные функции, которых может не быть в старых версиях. Это помогает нам повышать продуктивность.

  • Старое программное обеспечение, как правило, не получает исправления багов. Ваша система может оказаться под угрозой.

  • Как мы убедились на примере nslookup, не каждое заявление о том, что инструмент устарел, верно. В рамках домашнего задания советую вам убедиться, что ваши утилиты находятся в актуальном состоянии.

***

Делитесь в комментариях своим мнением об альтернативных инструментах Linux, вариантах их применения и эффективности по сравнению с устаревшими аналогами. А чтобы получать больше интересного контента, подписывайтесь на наш хабр-блог: мы регулярно переводим статьи зарубежных авторов и делимся экспертизой наших сотрудников.