Тема пользователей и их прав в системе в первую очередь относится к функционированию самой операционной системы. Оболочка лишь предоставляет утилиты, позволяющие анализировать доступы и изменять их.

Взаимодействие с операционной системой всегда ведётся от какого-то конкретного пользователя, созданного в системе. Команда whoami позволяет выяснить, кто же я такой:

$ whoami
rekoshed

Абсолютно любой процесс, запускаемый в операционной системе, стартует от имени некоторого пользователя. Соответственно, его возможности по влиянию на файловую систему ограничены теми правами, которые есть у пользователя, от имени которого процесс запущен. Обратите внимание на то, что я говорю не "пользователь запустил процесс", а "процесс запускается от имени пользователя". Дело в том, что присутствие пользователя для запуска необязательно. Да, работая в командной строке мы стартуем всё сами, но когда система загружается, то она стартует множество различных процессов и, как мы увидим ниже, для многих из них создаются собственные пользователи с ограниченным набором прав.

Команда ps (process status) выводит отчёт о работающих процессах. Информацию о том, какой процесс и под каким пользователем запущен, можно получить из вывода ps aux:

$ ps aux
# Левый столбец имя пользователя
rekoshed  1997  0.0  0.2 241028  8876 ?        Ssl  08:36   0:00 /usr/lib/gvfs/gvfs-udisks2-volume-monitor
root      1998  0.0  0.1   8084  4608 ?        Ss   08:36   0:00 /usr/lib/bluetooth/bluetoothd
rekoshed  2002  0.0  0.1 239364  7268 ?        Ssl  08:36   0:00 /usr/lib/gvfs/gvfs-gphoto2-volume-monitor
rekoshed  2018  0.0  0.1 236972  5972 ?        Ssl  08:36   0:00 /usr/lib/gvfs/gvfs-mtp-volume-monitor
root      2084  0.0  0.2 257220  9332 ?        Ssl  08:36   0:00 /usr/lib/upower/upowerd
rekoshed  2120  0.0  0.6 262120 27184 ?        Sl   08:36   0:00 /usr/bin/lxqt-powermanagement
rekoshed  2122  0.0  0.7 261612 29496 ?        Sl   08:36   0:00 /usr/bin/qlipper
rekoshed  2124  0.0  0.7 262840 29292 ?        Sl   08:36   0:00 /usr/bin/nm-tray
rekoshed  2178  0.1  1.2 368520 47944 ?        Sl   08:38   0:03 qterminal
rekoshed  2181  0.0  0.1  10860  4380 pts/0    Ss   08:38   0:00 /bin/bash
rekoshed  2258  0.0  0.2  28200  9412 pts/0    S+   08:38   0:00 mc
rekoshed  2260  0.0  0.1  10832  4260 pts/1    Ss+  08:38   0:00 bash -rcfile .bashrc
rekoshed  2269  0.0  0.0   2568   784 pts/0    S+   08:38   0:00 /bin/sh /tmp/mc-rekoshed/mcextXVE59Z
rekoshed  2270  0.0  0.0   2568   720 pts/0    S+   08:38   0:00 /bin/sh /usr/lib/mc/ext.d/web.sh open html
rekoshed  2271  0.0  0.0   2568  1828 pts/0    S+   08:38   0:00 /bin/sh /usr/bin/xdg-open /home/rekoshed/Github/Rekoshed.github.io/index.html
rekoshed  2335  0.0  0.0  12696  1528 pts/0    S+   08:38   0:00 cat
rekoshed  2336  0.0  0.0  12696  1616 pts/0    S+   08:38   0:00 cat
rekoshed  2343  0.0  0.1  10964  4596 pts/2    Ss+  08:39   0:00 /bin/bash
rekoshed  4682  0.0  0.1  10832  4352 pts/4    Ss   08:53   0:00 /bin/bash
rekoshed  4689  0.0  0.2  28360  9312 pts/4    S+   08:53   0:00 mc
rekoshed  4691  0.0  0.1  10836  5036 pts/5    Ss+  08:53   0:00 bash -rcfile .bashrc
root      4815  0.0  0.0      0     0 ?        I    08:56   0:00 [kworker/0:1-events]
rekoshed  4820  0.0  0.2 386756  8232 ?        Sl   08:56   0:00 /usr/lib/gvfs/gvfsd

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

$ ls -la
total 44
drwxr-xr-x 5 rekoshed rekoshed 4096 Aug 29 11:34 .
drwxr-xr-x 8 root     root     4096 Apr 26 10:38 ..
-rw------- 1 rekoshed rekoshed 2540 Aug 30 07:26 .bash_history
-rw-r--r-- 1 rekoshed rekoshed  220 Aug 31  2015 .bash_logout
-rw-r--r-- 1 rekoshed rekoshed 3771 Aug 31  2015 .bashrc
drwx------ 2 rekoshed rekoshed 4096 Mar 30 18:10 .cache
-rw------- 1 rekoshed rekoshed   55 Aug 28 18:49 .lesshst
drwxrwxr-x 2 rekoshed rekoshed 4096 Aug 29 08:35 .nano
-rw-r--r-- 1 rekoshed rekoshed  655 May 16  2017 .profile
-rw-rw-r-- 1 rekoshed rekoshed    0 Aug 29 11:27 renamed-file
drwx------ 2 rekoshed rekoshed 4096 Jan 22  2018 .ssh
-rw------- 1 rekoshed rekoshed  513 Aug 29 08:06 .viminfo

Третий столбец в этом выводе — как раз владелец. Единственная запись, которая выбивается из всего списка это .., то есть родительская директория. Её владельцем является root, о котором мы позже поговорим. Если хорошо подумать, то это логично — ведь директория /home не является собственностью пользователей системы:

$ ls -la /home/
total 32
drwxr-xr-x  8 root              root              4096 Apr 26 10:38 .
drwxr-xr-x 23 root              root              4096 Aug 27 06:53 ..
drwxr-xr-x  5 egor.v       egor.v       4096 Jan 22  2018 egor.v
drwxr-xr-x  5 rekoshed          rekoshed          4096 Aug 29 11:34 rekoshed
drwxr-xr-x  4 robot            robot            4096 Apr 26 10:05 robot
drwxr-xr-x  4 robot.d          robot.d          4096 Apr 26 10:41 robot.d

Каждый каталог в директории /home является домашним каталогом конкретного пользователя. Поэтому они все имеют разных владельцев, как правило, совпадающих с именем директории.

Имя пользователя в системе должно быть уникальным, но его можно менять. Если посмотреть под капот работы этой системы, то мы увидим, что имя пользователя связано с идентификатором, называемым UID. Это число, которое и определяет пользователя. Если поменяется имя пользователя, но идентификатор останется прежним, то все доступы останутся. Если же сменится идентификатор, то фактически сменится и пользователь. Соответственно, новый пользователь потеряет доступы ко всему старому. Посмотреть свой идентификатор можно разными способами. Первый способ — с помощью команды id:

$ id
uid=1002(rekoshed) gid=1002(rekoshed) groups=1002(rekoshed),999(docker)

Второй способ связан с просмотром одного важного файла, который является основным хранилищем пользователей в *nix системах. Да, это обычный текстовый файл, как и всё остальное.

$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
rekoshed:x:1002:1002::/home/rekoshed:/bin/bash

Схема записей в файле /ect/passwd

Кроме имени и идентификатора, здесь также указана домашняя директория пользователя (и её можно поменять), а так же шелл по умолчанию. Запись /usr/sbin/nologin говорит о том, что данный пользователь не может входить в систему. Такие пользователи нужны для запуска программ, имеющих ограниченные права, и им, естественно, не нужно входить в систему.

Кроме имени, у пользователей *nix систем есть связанное с ним понятие группа. Группа, как можно догадаться из названия, создана для группового доступа к разделяемому (общему) ресурсу (например, файлу). Например, у нас есть группа разработчиков, которые регулярно ходят на сервер, и им нужно дать одинаковые возможности по управлению определёнными файлами. Так как владелец у файла ровно один, то мы не можем решить этот вопрос через смену владельца, но можем через создание группы. Достаточно её создать и привязать к самому пользователю. Группы, ассоциированные с текущим пользователем, показываются в выводе команды id:

$ id
uid=1002(rekoshed) gid=1002(rekoshed) groups=1002(rekoshed),999(docker)

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

В любой *nix системе присутствует специальный пользователь root, или, как говорят, суперпользователь. Главная его особенность — это идентификатор со значением 0 (а имя в теории можно поменять). Этот пользователь имеет особое значение для системы и может выполнять абсолютно любые действия в системе. У пользователя root в файле /etc/passwd будет вот такая запись:

Схема записей в /ect/passwd польлзователя root

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

Sudo

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

Ситуаций, в которых необходимо повышать привилегии и выполнять команды от рута (пользователя root), довольно много. С некоторыми мы уже столкнулись, с другими познакомимся в следующих уроках:

Стать другим пользователем, находясь прямо в системе, можно с помощью утилиты su (substitute user, switch user). Когда-то такой способ был основным, но сейчас он устарел и крайне не рекомендуется к использованию. Подробнее об этом можно прочитать в статье из дополнительных материалов. Основной способ повышать привилегии в современных системах — утилита sudo (substitute user and do — дословно "подменить пользователя и выполнить").

Используется судо очень просто, достаточно поставить её слева от любой команды и выполнить. По умолчанию она пытается повысить привилегии до суперпользователя:

# Нет прав на выполнение
$ touch /etc/myfile
touch: cannot touch '/etc/myfile': Permission denied

# С sudo все работает
$ sudo touch /etc/myfile

# Видно что владелец файла root
$ stat /etc/myfile
  File: '/etc/myfile'
  Size: 0           Blocks: 0          IO Block: 4096   regular empty file
Device: ca01h/51713d    Inode: 2761        Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)

# Нет прав на удаление
$ rm /etc/myfile
rm: remove write-protected regular empty file '/etc/myfile'? y
rm: cannot remove '/etc/myfile': Permission denied

# Опять помогло sudo
$ sudo rm /etc/myfile
$

В зависимости от настроек sudo в системе, эта утилита может попросить ваш пароль для входа, либо вообще откажется работать, сказав, что у вас нет права её использовать. Как правило, в Ubuntu судо спрашивает пароль и запоминает его на 5 минут. На протяжении этого времени вы можете использовать sudo, не вводя пароль каждый раз.

Иногда бывает нужно выполнить команду из под пользователя, отличного от root. Тогда придётся добавить флаг -u:

$ sudo -u nobody mkdir /tmp/test
# Файл создан от nobody
$ stat /tmp/test
  File: '/tmp/test'
  Size: 4096        Blocks: 8          IO Block: 4096   directory
Device: ca01h/51713d    Inode: 4577        Links: 2
Access: (0755/drwxr-xr-x)  Uid: (65534/  nobody)   Gid: (65534/ nogroup)

Если стоит задача произвести сразу пачку действий от имени другого пользователя, то для этого можно запустить новую сессию поверх текущей:

$ sudo -i
$ id
uid=0(root) gid=0(root) groups=0(root)

Главное — не забыть переключиться обратно после завершения необходимых манипуляций. Для этого наберите exit.

Права доступа

Частая ошибка, с которой встречаются разработчики — ошибка доступа:

$ touch /etc/myfile
touch: cannot touch '/etc/myfile': Permission denied

Она говорит о том, что текущий пользователь не имеет прав на создание файлов в каталоге /etc. Почему? Давайте разбираться.

Кроме имени пользователя и группы, с каждым файлом ассоциированы права доступа: r — чтение, w — запись и x — исполнение. Причём, эти права задаются для трёх типов пользователей: владельца (Owner), пользователей, входящих в ту же группу (Group) и остальных (Other) — тех, кто не попал в предыдущие две. Разберём на примере:

# Пример строчки из вывода команды ls -la
-rw-r--r-- 1 rekoshed rekoshed 3771 Aug 31  2015 .bashrc

Запись слева представляет из себя один из вариантов описания прав доступа (permissions). Для удобства чтения разделим эту запись на группы символов - rw- r-- r--. Символ - в этой записи говорит о том, что перед нами обычный файл. За ним следует три группы, в каждой из которых по три символа. Каждая группа описывает доступы для разных типов пользователей. Первая описывает права доступа для владельца файла. rw- означает, что владелец этого файла может как читать (r) этот файл, так и писать (w) в него. Последний прочерк означает, что этот файл нельзя исполнять. Исполнение описывается символом x и будет рассмотрено в следующем уроке. Не важно, какой файл или директорию мы смотрим — порядок прав в этой группе всегда один и тот же чтение-запись-исполнение, а прочерк означает отсутствие данного права.

Следующая группа прав относится к тем, кто входит в группу rekoshed, так как именно этой группе принадлежит данный файл. Запись r-- говорит о наличии доступа только для чтения, а изменение запрещено. То же самое касается и тех, кто не входит в эту группу, то есть набор прав у последних двух одинаковый.

File Permissions

Попробуйте ответить на вопрос с подвохом: а кто может удалить этот файл? Для ответа на этот вопрос важно знать владельца, группу и права той директории, в которой лежит файл .bashrc. Сам файл не может обозначить прав на своё удаление, они всегда берутся из того места, где он находится. Удалить файл можно только, если у вас есть возможность писать в эту директорию (в соответствии с тем, к какому типу пользователей вы относитесь).

$ ls -la /home/ | grep kirill
drwxr-xr-x  5 rekoshed          rekoshed          4096 Aug 29 11:34 rekoshed

Домашняя директория имеет другие права. Первое отличие — это d вместо - в самом начале. d говорит о том, что перед нами директория. Права для владельца rwx, а для всех остальных r-x. Из этого описания видно, что кроме пользователя никто не может писать внутрь домашней директории этого пользователя.

Что такое x в отношении директорий? Это право позволяет перемещаться в директорию и обращаться ко всем расположенным в ней файлам и каталогам. Обращаться можно при условии, что эти файлы доступны на чтение или запись или выполнение: например, если положить доступный на чтение файл в директорию с правом x, то вы сможете прочитать этот файл. Если же убрать с директории право x, то вы вовсе лишитесь доступа к файлу.

Но что тогда такое чтение? Здесь всё более интуитивно понятно: директория, по сути, является списком файлов, поэтому право на чтение позволяет прочитать этот список файлов, а именно вывести список имён файлов, содержащихся в директории. Однако, если хотите посмотреть не простой список имён файлов, а список с дополнительной информацией (как при выводе ls -l), то требуется ещё и право x, потому что в этом случае надо обращаться к файлам за их метаданными (владелец, группа, дата изменения, права и др.). В любом случае, без права r на каталог вы не сможете посмотреть его содержимое.

В литературе (статьях, книгах, мануалах) иногда используется другой способ описания прав доступа: 775. Это не одно число, а три числа, каждое из которых представляет собой группу rwx для наших типов пользователя в том же порядке: для владельца, входящих в группу и всех остальных. 0 — означает, что нет никаких прав для данного типа пользователей.

A B C D
1 # Permission rwx Binary
2 7 read, write and execute rwx 111
3 6 read and write rw- 110
4 5 read and execute r-x 101
5 4 read only r-- 100
6 3 write and execute -wx 011
7 2 write only -w- 010
8 1 execute only --x 001

drwxr-xr-x в числовой форме соответствует 755, а -rw-r--r--644.

Однако пользователь root находится вне этой системы. Для него не имеет никакого значения наличие любых прав — рут может всё.