Полезная информация для изучающих Linux.
pwd
Вывести текущую (рабочую) директорию.
[user@testhost ~]$ pwd /home/user
date
Вывести текущую дату и время системы.
[user@testhost ~]$ date Mon Dec 16 13:37:07 UTC 2019 [user@testhost ~]$ date +%s 1576503430
w
Данная команда показывает, кто залогинен в системе. Помимо этого также на экран выводится uptime и LA (load average).
[user@testhost ~]$ w 05:47:17 up 377 days, 17:57, 1 user, load average: 0,00, 0,01, 0,05 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT user pts/0 32.175.94.241 05:47 2.00s 0.01s 0.00s w
ls
Вывести содержимое директории. Если не передать путь, то выведется содержимое текущей директории.
[user@testhost ~]$ pwd /home/user [user@testhost ~]$ ls qqq [user@testhost ~]$ ls /home/user qqq [user@testhost ~]$ ls / bin boot cgroup dev etc home lib lib64 local lost+found media mnt opt proc root run sbin selinux srv swap sys tmp usr var
Лично я часто использую опции -l (long listing format — вывод в колонку с дополнительной информацией о файлах), -t (сортировка по времени изменения файла/директории) и -r (обратная сортировка — в сочетании с -t наиболее «свежие» файлы будут внизу):
[user@testhost ~]$ ls -ltr / total 4194416 drwxr-xr-x 2 root root 4096 Jan 6 2012 srv drwxr-xr-x 2 root root 4096 Jan 6 2012 selinux drwxr-xr-x 2 root root 4096 Jan 6 2012 mnt drwxr-xr-x 2 root root 4096 Jan 6 2012 media drwx------ 2 root root 16384 Oct 1 2017 lost+found drwxr-xr-x 2 root root 4096 Oct 1 2017 local drwxr-xr-x 13 root root 4096 Oct 1 2017 usr drwxr-xr-x 11 root root 4096 Apr 10 2018 cgroup drwxr-xr-x 4 root root 4096 Apr 10 2018 run -rw------- 1 root root 4294967296 Sep 10 2018 swap dr-xr-xr-x 10 root root 4096 Dec 13 2018 lib drwxr-xr-x 6 root root 4096 Mar 7 2019 opt drwxr-xr-x 20 root root 4096 Mar 19 2019 var dr-xr-xr-x 10 root root 12288 Apr 9 2019 lib64 dr-xr-xr-x 2 root root 4096 Apr 9 2019 bin dr-xr-xr-x 4 root root 4096 Apr 9 2019 boot dr-xr-xr-x 2 root root 12288 Apr 9 2019 sbin dr-xr-xr-x 3229 root root 0 Jul 2 10:19 proc drwxr-xr-x 34 root root 4096 Oct 28 13:27 home drwxr-xr-x 93 root root 4096 Oct 30 16:00 etc dr-xr-x--- 11 root root 4096 Nov 1 13:02 root dr-xr-xr-x 13 root root 0 Nov 13 20:28 sys drwxr-xr-x 16 root root 2740 Nov 26 08:55 dev drwxrwxrwt 3 root root 4096 Nov 26 08:57 tmp
Есть 2 специальных имени директории: "." и "..". Первое означает текущую директорию, второе — родительскую директорию. Их бывает удобно использовать в различных командах, в частности, ls:
[user@testhost home]$ pwd /home [user@testhost home]$ ls .. bin boot cgroup dev etc home lib lib64 local lost+found media mnt opt proc root run sbin selinux srv swap sys tmp usr var [user@testhost home]$ ls ../home/user/ qqq
Также есть полезная опция для вывода скрытых файлов (начинаются на ".") — -a:
[user@testhost ~]$ ls -a . .. 1 .bash_history .bash_logout .bash_profile .bashrc .lesshst man_signal man_signal_error_log .mongorc.js .ssh temp test .viminfo
И еще можно использовать опцию -h — вывод в human readable формате (обратите внимание на размеры файлов):
[user@testhost ~]$ ls -ltrh total 16K -rwxrwx--x 1 user user 31 Nov 26 11:09 temp -rw-rw-r-- 1 user user 6.0K Dec 3 16:02 1 drwxrwxr-x 2 user user 4.0K Dec 4 10:39 test
cd
Изменить текущую директорию.
[user@testhost ~]$ pwd /home/user [user@testhost ~]$ cd /home/ [user@testhost home]$ pwd /home
Если не передавать имя директории в качестве аргумента, будет использоваться переменная окружения $HOME, то есть домашняя директория. Также может быть удобно использовать `~` — специальный символ, означающий $HOME:
[user@testhost etc]$ pwd /etc [user@testhost etc]$ cd ~/test/ [user@testhost test]$ pwd /home/user/test
mkdir
Создать директорию.
[user@testhost ~]$ mkdir test [user@testhost ~]$ ls -ltr total 38184 -rw-rw-r-- 1 user user 39091284 Nov 22 14:14 qqq drwxrwxr-x 2 user user 4096 Nov 26 10:29 test
Иногда нужно создать определенную структуру директорий: например, директорию в директории, которой не существует. Чтобы не вводить несколько раз подряд mkdir, можно использовать опцию -p — она позволяет создать все недостающие директории в иерархии. Также с этой опцией mkdir не вернет ошибку, если директория существует.
[user@testhost ~]$ ls qqq test [user@testhost ~]$ mkdir test2/subtest mkdir: cannot create directory ‘test2/subtest’: No such file or directory [user@testhost ~]$ mkdir -p test2/subtest [user@testhost ~]$ ls qqq test test2 [user@testhost ~]$ ls test2/ subtest [user@testhost ~]$ mkdir test2/subtest mkdir: cannot create directory ‘test2/subtest’: File exists [user@testhost ~]$ mkdir -p test2/subtest [user@testhost ~]$ ls test2/ subtest
rm
Удалить файл.
[user@testhost ~]$ ls qqq test test2 [user@testhost ~]$ rm qqq [user@testhost ~]$ ls test test2
Опция -r позволяет рекурсивно удалять директории со всем их содержимым, опция -f позволяет игнорировать ошибки при удалении (например, о несуществующем файле). Эти опции позволяют, грубо говоря, гарантированно удалить всю иерархию файлов и директорий (если на это есть права у пользователя), поэтому, их нужно использовать с осторожностью (классический пример-шутка — "rm -rf /", при определенных обстоятельствах удалит вам если не всю систему, то очень много важных для её работоспособности файлов).
[user@testhost ~]$ ls test test2 [user@testhost ~]$ ls -ltr test2/ total 4 -rw-rw-r-- 1 user user 0 Nov 26 10:40 temp drwxrwxr-x 2 user user 4096 Nov 26 10:40 temp_dir [user@testhost ~]$ rm -rf test2 [user@testhost ~]$ ls test
cp
Копировать файл или директорию.
[user@testhost ~]$ ls temp test [user@testhost ~]$ cp temp temp_clone [user@testhost ~]$ ls temp temp_clone test
У этой команды также есть опции -r и -f, их можно использовать, чтобы гарантированно скопировать иерархию директорий и папок в другое место.
mv
Переместить или переименовать файл или директорию.
[user@testhost ~]$ ls -ltr total 4 drwxrwxr-x 2 user user 4096 Nov 26 10:29 test -rw-rw-r-- 1 user user 0 Nov 26 10:45 temp -rw-rw-r-- 1 user user 0 Nov 26 10:46 temp_clone [user@testhost ~]$ ls test [user@testhost ~]$ mv test test_renamed [user@testhost ~]$ mv temp_clone test_renamed/ [user@testhost ~]$ ls temp test_renamed [user@testhost ~]$ ls test_renamed/ temp_clone
cat
Вывести содержимое файла (или файлов).
[user@testhost ~]$ cat temp Content of a file. Lalalala...
Также стоит обратить внимание на команды head (вывести n первых строк или байт файла) и tail (о ней — далее).
tail
Вывести n последних строк или байт файла.
[user@testhost ~]$ tail -1 temp Lalalala...
Очень полезной является опция -f — она позволяет выводить новые данные в файле в реальном времени.
less
Иногда текстовый файл слишком большой, и неудобно выводить его командой cat. Тогда можно открыть его с помощью команды less: файл будет выводиться по частям, доступна навигация по этим частям, поиск и прочий простой функционал.
[user@testhost ~]$ less temp
Также может оказаться удобным вариант использования less с конвейером (pipe):
[user@testhost ~]$ grep "ERROR" /tmp/some.log | less
ps
Вывести список процессов.
[user@testhost ~]$ ps PID TTY TIME CMD 761020 pts/2 00:00:00 bash 809720 pts/2 00:00:00 ps
Я сам обычно использую BSD опции "aux" — вывести все процессы в системе (так как процессов может быть много, я вывел только первые 5 из них, использовав конвейер (pipe) и команду head):
[user@testhost ~]$ ps aux | head -5 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 19692 2600 ? Ss Jul02 0:10 /sbin/init root 2 0.0 0.0 0 0 ? S Jul02 0:03 [kthreadd] root 4 0.0 0.0 0 0 ? I< Jul02 0:00 [kworker/0:0H] root 6 0.0 0.0 0 0 ? I< Jul02 0:00 [mm_percpu_wq]
Многие также используют BSD опции "axjf", что позволяет вывести дерево процессов (здесь я убрал часть вывода для демонстрации):
[user@testhost ~]$ ps axjf PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 0 2 0 0 ? -1 S 0 0:03 [kthreadd] 2 4 0 0 ? -1 I< 0 0:00 \_ [kworker/0:0H] 2 6 0 0 ? -1 I< 0 0:00 \_ [mm_percpu_wq] 2 7 0 0 ? -1 S 0 4:08 \_ [ksoftirqd/0] ... ... ... 1 4293 4293 4293 tty6 4293 Ss+ 0 0:00 /sbin/mingetty /dev/tty6 1 532967 532964 532964 ? -1 Sl 495 0:00 /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --group td-agent --daemon /var/run/td-agent/td-agent.pid 532967 532970 532964 532964 ? -1 Sl 495 803:06 \_ /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --group td-agent --daemon /var/run/td-agent/td-agent.pid 1 537162 533357 532322 ? -1 Sl 0 5067:43 /usr/bin/dockerd --default-ulimit nofile=262144:262144 --dns=172.17.0.1 537162 537177 537177 537177 ? -1 Ssl 0 4649:28 \_ docker-containerd --config /var/run/docker/containerd/containerd.toml 537177 537579 537579 537177 ? -1 Sl 0 4:48 | \_ docker-containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/0ee89b20deb3cf08648cd92e1f3e3c661ccffef7a0971 537579 537642 537642 537642 ? -1 Ss 1000 32:11 | | \_ /usr/bin/python /usr/bin/supervisord -c /etc/supervisord/api.conf 537642 539764 539764 537642 ? -1 S 1000 0:00 | | \_ sh -c echo "READY"; while read -r line; do echo "$line"; supervisorctl shutdown; done 537642 539767 539767 537642 ? -1 S 1000 5:09 | | \_ php-fpm: master process (/etc/php73/php-fpm.conf) 539767 783097 539767 537642 ? -1 S 1000 0:00 | | | \_ php-fpm: pool test 539767 783131 539767 537642 ? -1 S 1000 0:00 | | | \_ php-fpm: pool test 539767 783185 539767 537642 ? -1 S 1000 0:00 | | | \_ php-fpm: pool test ... ... ...
У этой команды много различных опций, так что при активном использовании рекомендую ознакомиться с документацией. Для большинства же случаев хватит просто знать "ps aux".
kill
Послать сигнал процессу. По умолчанию посылается сигнал SIGTERM, который завершает процесс.
[user@testhost ~]$ ps ux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND 531 1027147 0.0 0.0 119956 4260 ? S 14:51 0:00 sshd: user@pts/1 531 1027149 0.0 0.0 115408 3396 pts/1 Ss 14:51 0:00 -bash 531 1027170 0.0 0.0 119956 4136 ? R 14:51 0:00 sshd: user@pts/2 531 1027180 0.0 0.0 115408 3564 pts/2 Ss 14:51 0:00 -bash 531 1033727 0.0 0.0 107960 708 pts/1 S+ 15:17 0:00 sleep 300 531 1033752 0.0 0.0 117264 2604 pts/2 R+ 15:17 0:00 ps ux [user@testhost ~]$ kill 1033727 [user@testhost ~]$ ps ux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND 531 1027147 0.0 0.0 119956 4260 ? S 14:51 0:00 sshd: user@pts/1 531 1027149 0.0 0.0 115408 3396 pts/1 Ss+ 14:51 0:00 -bash 531 1027170 0.0 0.0 119956 4136 ? R 14:51 0:00 sshd: user@pts/2 531 1027180 0.0 0.0 115408 3564 pts/2 Ss 14:51 0:00 -bash 531 1033808 0.0 0.0 117268 2492 pts/2 R+ 15:17 0:00 ps ux
Так как процесс может иметь обработчики сигналов, kill не всегда приводит к ожидаемому результату — моментальному завершению процесса. Чтобы «убить» процесс наверняка, нужно послать процессу сигнал SIGKILL. Однако это может привести к потере данных (например, если процесс перед завершением должен сохранить какую-то информацию на диск), так что нужно пользоваться такой командой осторожно. Номер сигнала SIGKILL — 9, поэтому короткий вариант команды выглядит так:
[user@testhost ~]$ ps ux | grep sleep 531 1034930 0.0 0.0 107960 636 pts/1 S+ 15:21 0:00 sleep 300 531 1034953 0.0 0.0 110516 2104 pts/2 S+ 15:21 0:00 grep --color=auto sleep [user@testhost ~]$ kill -9 1034930 [user@testhost ~]$ ps ux | grep sleep 531 1035004 0.0 0.0 110516 2092 pts/2 S+ 15:22 0:00 grep --color=auto sleep
Помимо упомянутых SIGTERM и SIGKILL существует еще множество различных сигналов, их список можно легко найти в интернете. И не забывайте, что сигналы SIGKILL и SIGSTOP не могут быть перехвачены или проигнорированы.
ping
Послать хосту ICMP пакет ECHO_REQUEST.
[user@testhost ~]$ ping google.com PING google.com (172.217.15.78) 56(84) bytes of data. 64 bytes from iad23s63-in-f14.1e100.net (172.217.15.78): icmp_seq=1 ttl=47 time=1.85 ms 64 bytes from iad23s63-in-f14.1e100.net (172.217.15.78): icmp_seq=2 ttl=47 time=1.48 ms 64 bytes from iad23s63-in-f14.1e100.net (172.217.15.78): icmp_seq=3 ttl=47 time=1.45 ms 64 bytes from iad23s63-in-f14.1e100.net (172.217.15.78): icmp_seq=4 ttl=47 time=1.46 ms 64 bytes from iad23s63-in-f14.1e100.net (172.217.15.78): icmp_seq=5 ttl=47 time=1.45 ms ^C --- google.com ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4006ms rtt min/avg/max/mdev = 1.453/1.541/1.850/0.156 ms
По умолчанию ping работает, пока его не завершить вручную. Поэтому может быть полезна опция -c — количество пакетов, после отправки которых ping завершится самостоятельно. Ещё одна опция, которую я иногда использую — -i, интервал между посылками пакетов.
[user@testhost ~]$ ping -c 3 -i 5 google.com PING google.com (172.217.5.238) 56(84) bytes of data. 64 bytes from iad30s07-in-f238.1e100.net (172.217.5.238): icmp_seq=1 ttl=47 time=1.55 ms 64 bytes from iad30s07-in-f14.1e100.net (172.217.5.238): icmp_seq=2 ttl=47 time=1.17 ms 64 bytes from iad30s07-in-f14.1e100.net (172.217.5.238): icmp_seq=3 ttl=47 time=1.16 ms --- google.com ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 10006ms rtt min/avg/max/mdev = 1.162/1.295/1.551/0.181 ms
ssh
OpenSSH SSH клиент, позволяет подключаться к удаленному хосту.
MacBook-Pro-User:~ user$ ssh user@11.11.22.22 Last login: Tue Nov 26 11:27:39 2019 from another_host [user@testhost ~]$ hostname testhost
Есть много нюансов в использовании SSH, также этот клиент обладает большим количеством возможностей, поэтому при желании (или необходимости) можно почитать про это более подробно.
scp
Копировать файлы между хостами (для этого используется ssh).
[user@testhost ~]$ pwd /home/user [user@testhost ~]$ ls temp test_renamed [user@testhost ~]$ exit logout Connection to 11.11.22.22 closed. MacBook-Pro-Aleksandr:~ user$ scp user@11.11.22.22:/home/user/temp Downloads/ temp 100% 31 0.2KB/s 00:00 MacBook-Pro-Aleksandr:~ user$ cat Downloads/temp Content of a file. Lalalala...
rsync
Также для синхронизации директорий между хостами можно использовать rsync (-a — archive mode, позволяет скопировать полностью всё содержимое директории «как есть», -v — вывод на консоль дополнительной информации):
MacBook-Pro-User:~ user$ ls Downloads/user ls: Downloads/user: No such file or directory MacBook-Pro-User:~ user$ rsync -av user@testhost:/home/user Downloads receiving file list ... done user/ user/.bash_history user/.bash_logout user/.bash_profile user/.bashrc user/.lesshst user/.mongorc.js user/.viminfo user/1 user/man_signal user/man_signal_error_log user/temp user/.ssh/ user/.ssh/authorized_keys user/test/ user/test/created_today user/test/temp_clone sent 346 bytes received 29210 bytes 11822.40 bytes/sec total size is 28079 speedup is 0.95 MacBook-Pro-User:~ user$ ls -a Downloads/user . .bash_history .bash_profile .lesshst .ssh 1 man_signal_error_log test .. .bash_logout .bashrc .mongorc.js .viminfo man_signal temp
echo
Вывести на экран строку текста.
[user@testhost ~]$ echo "Hello" Hello
Здесь заслуживают внимания опции -n — не дополнять строку переносом строки в конце, и -e — включить интерпретацию экранирования с помощью "\".
[user@testhost ~]$ echo "\tHello\n" \tHello\n [user@testhost ~]$ echo -n "\tHello\n" \tHello\n[user@testhost ~]$ [user@testhost ~]$ echo -ne "\tHello\n" Hello
Также с помощью этой команды можно выводить значения переменных. Например, в Linux exit code последней завершенной команды хранится в специальной переменной $?, и таким образом можно узнать, какая именно ошибка произошла в последнем запущенном приложении:
[user@testhost ~]$ ls # ошибки не будет 1 man_signal man_signal_error_log temp test [user@testhost ~]$ echo $? # получим 0 — ошибки не было 0 [user@testhost ~]$ ls qwerty # будет ошибка ls: cannot access qwerty: No such file or directory [user@testhost ~]$ echo $? # получим 2 — Misuse of shell builtins (according to Bash documentation) 2 [user@testhost ~]$ echo $? # последний echo отработал без ошибок, получим 0 0
telnet
Клиент для протокола TELNET. Используется для коммуникации с другим хостом.
[user@testhost ~]$ telnet example.com 80 Trying 93.184.216.34... Connected to example.com. Escape character is '^]'. GET / HTTP/1.1 Host: example.com HTTP/1.1 200 OK Cache-Control: max-age=604800 Content-Type: text/html; charset=UTF-8 Date: Tue, 26 Nov 2019 11:59:18 GMT Etag: "3147526947+gzip+ident" Expires: Tue, 03 Dec 2019 11:59:18 GMT Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT Server: ECS (dcb/7F3B) Vary: Accept-Encoding X-Cache: HIT Content-Length: 1256 ... здесь было тело ответа, которое я вырезал руками ...
Если нужно использовать протокол TLS (напомню, что SSL давно устарел), то telnet для этих целей не подойдёт. Зато подойдёт клиент openssl