Info
Content

1. Работа в операционной системе UNIX

Имя файла является атрибутом файловой системы, а не набора некоторых данных на диске, который не имеет имени как такового

Каждый файл имеет связанные с ним метаданные, которые хранятся в индексных дескрипторах - inode, и содержат в себе все характеристики файла, которые позволяют ОС работать с ним
В частности метаданные содержат указатели на дисковые блоки хранения данных файла

Имя файла является указателем на метаданные
В то время как метаданные никак не указывают на имя (односторонняя связь)
Отсюда становится понятно как работают хардлинки

Существует 6 типов файлов (от типа зависят возможные действия, назначение итд):

  • обычный файл
  • каталог
  • специальный файл устройства
  • именованный канал или fifo
  • символическая связь
  • сокет

Обычный файл для операционной системы это просто набор байтов, вся их обработка выполняется уровнем выше (прикладной программой)

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

Специальный файл устройства обеспечивает доступ к физическому устройству
Бывают символьные и блочные, Символьные используются для небуферизованного обмена, а блочные позволяют обмениваться пакетами фиксированной длины - блоками

FIFO позволяет передвать данные между процессами

Связь. Записи в каталогах связывают имя файла и метаданные (имя -> inode), метаданные связываются с блоками данных (inode -> blocks)
Соответственно на одну и ту же айноду может указывать несколько имен и один файл может иметь несколько имен

Файлу безразлично какие имена он имеет, но не безразлично их количество
Если у файла не осталось имен в файловой системе, то он должен быть удален

Это называется жесткой связью (hardlink)

root@mars:/var/tmp/test/test# touch file1
root@mars:/var/tmp/test/test# ln file1 file2
root@mars:/var/tmp/test/test# ls -li
total 0
4856290 -rw-r--r-- 2 root root 0 Mar 19 20:33 file1
4856290 -rw-r--r-- 2 root root 0 Mar 19 20:33 file2
root@mars:/var/tmp/test/test# touch otherfile
root@mars:/var/tmp/test/test# ls -li
total 0
4856290 -rw-r--r-- 2 root root 0 Mar 19 20:33 file1
4856290 -rw-r--r-- 2 root root 0 Mar 19 20:33 file2
4856297 -rw-r--r-- 1 root root 0 Mar 19 20:33 otherfile
root@mars:/var/tmp/test/test# echo 'test' > file1
root@mars:/var/tmp/test/test# cat file2
test
root@mars:/var/tmp/test/test# 

Кроме одинаковых inode, выше виден еще и третий столбец (числа 2/1), он как раз и указывает на количество хардлинков

Символьная связь ведет себя иначе
Содержимое символьной ссылки это имя целевого файла
На примере видна логика работы

root@mars:/var/tmp/test/test/test# echo 'niga1' > file
root@mars:/var/tmp/test/test/test# mkdir test
root@mars:/var/tmp/test/test/test# cd test
root@mars:/var/tmp/test/test/test/test# echo 'niga2' > file
root@mars:/var/tmp/test/test/test/test# cd ..
root@mars:/var/tmp/test/test/test# tree
.
|-- file
`-- test
    `-- file

1 directory, 2 files

# Подготовили площадку, имеем два файла с одинаковым именем но с разным содержимым

root@mars:/var/tmp/test/test/test# ln -s file link

# Делаем ссылку с относительным именем цели и тестим

root@mars:/var/tmp/test/test/test# cat link 
niga1
root@mars:/var/tmp/test/test/test# mv link test/.
root@mars:/var/tmp/test/test/test# cat test/link 
niga2

Символьная ссылка это особый тип файла
ОС ведет себя особым образом при работе с ним

Хардлинк имеет ограничение, он может существовать только в рамках одной ФС, тогда как символические ссылки могут быть cross file system

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


lost+found - как ранее говорилось, у файла должен быть минимум один хардлинк, иначе файл должен быть удален
Но "должен" не равно "будет"
Поэтому при ошибках остановки ОС или аппаратных сбоях могут возникать ситуации когда на диске есть правильная структура файла но для него отсутсвует имя в каком-либо каталоге
Системы проверки и восстановления ФС кладут такие файлы в lost+found


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


При создании файла ему назначается владелец-пользователь и владелец-группа
Владелец-группа не обязательно должен быть первичной группой пользователя-создателя
Например в freebsd владелец-группа для файла наследуется от вышестоящего каталога

На самом деле файл создает не пользователь а процесс который пользователь породил
У этого процесса есть разные аттрибуты
Такие как UID, EUID, GID и EGID
От них как раз и зависит очень многое


Для бинарей чтобы запуститься достаточно иметь права на исполнение
А для скритов также требуется право на чтение
upd: не совсем

root@two:~# cat scr
#!/bin/bash
echo test

root@two:~# ls -l
total 4
-rw-r--r-- 1 root root 22 May  6 06:08 scr

root@two:~# . scr
test

root@two:~# chmod 100 scr

root@two:~# ls -l
total 4
---x------ 1 root root 22 May  6 06:08 scr

root@two:~# ./scr
test

Символьные ссылки вообще не имеют своих прав, они наследуют права от целевого файла

У каталогов права используются немного иначе
Право чтения каталога позволяет прочитать его, те получить список имен файлов внутри (только имена и только на один уровень вглубь) = ls
Право исполнения на каталоге позволит пройти внутрь и обратиться к метаданным файлов внутри каталога = ls -l

Чтобы зайти в папку не обязательно иметь права на ее чтение

macbook:a vandud$ pwd
/tmp/a

macbook:a vandud$ ls b
ls: b: Permission denied

macbook:a vandud$ tree
.
└── b [error opening dir]
1 directory, 0 files

macbook:a vandud$ cd b/c

macbook:c vandud$ ls -l
total 0
-rwx------  1 vandud  wheel  0 Mar 26 19:36 file

Как видно в примере выше можно перескочить папку
Достаточно лишь иметь право зайти в нее и не обязательно ее читать

Например когда ты заранее знаешь путь по которому тебе нужно оказаться

Биты x и r независимы
С помощью различных их комбинаций можно добиваться инетересных эффектов

macbook:test vandud$ mkdir a
macbook:test vandud$ chmod a-r+x a
macbook:test vandud$ touch a/file
macbook:test vandud$ ls -l a
ls: a: Permission denied
macbook:test vandud$ echo 'text' > a/file
macbook:test vandud$ cat a/file # <tab> тут не срабатывает
text

Чтобы удалить файл достаточно иметь право на запись в папку в которой он находится (не нужно иметь прав на сам файл)
Право на запись в каталог дает много полномочий
Такая проблема решается Sticky bit'ом на каталог


Даже если пользователь 'user' входит в группу 'group', он не сможет прочитать 'file', зато все остальные смогут

----rw-r-- 2 user group 0 Mar 19 20:33 file

Выше было про основные аттрибуты файлов
Но существуют также и дополнительные
Они выставляются так же командой chmod, но используются другие буквы

Code Name Description
t Sticky bit Сохранить образ выполняемого файла в памяти после завершения, чтобы в следующий раз он запустился быстрее
s Set UID, SUID Установить UID процесса при выполнении, позволяет изменить права пользователя на время выполнения файла
s Set GID, SGID Установить GID процесса при выполнении
l Блокирование Установить обязательное блокирование файла

SUID и SGID следует высталять осторожно, потому что в процессе выполнения программа может запускать другие программы и права будут наследоваться

SUID и SGID позволяют запускать файл с правами владельца-пользователя или владельца-группы

i.dudin_pro@mon-test-vm-01y:/usr/bin$ ls -l passwd
-rwsr-xr-x 1 root root 54192 May 17  2017 passwd

passwd как раз работает за счет SUID. Потому что пароли хранятся в системном файле /etc/shadow и пользователям как-то нужно иметь возможно его изменять (чтобы изменить свой пароль в нем)

Блокирование позволяет устранить возможность конфликта когда две+ задачи работают с одним файлом


Sticky bit для каталога позволяет пользователю удалять только те файлы которыми он владеет или имеет права на запись (при наличие права на запись в каталог)
Так работает раздел /tmp, в него могут писать все, но удалить можно только свое

i.dudin_pro@mon-test-vm-01y:~/test$ ls -la
total 12
drwxr-xr-x 3 i.dudin_pro linux_users 4096 Mar 26 16:18 .
drwxr-xr-x 5 i.dudin_pro linux_users 4096 Mar 26 13:56 ..
drwxr-xr-x 2 i.dudin_pro linux_users 4096 Mar 26 16:18 dir
-rw-r--r-- 1 i.dudin_pro linux_users    0 Mar 26 16:18 file
i.dudin_pro@mon-test-vm-01y:~/test$ chmod +t dir/
i.dudin_pro@mon-test-vm-01y:~/test$ chmod +t file ### можно использовать букву 'a' или 'o' или никакую как в этой строке
i.dudin_pro@mon-test-vm-01y:~/test$ ls -l
total 4
drwxr-xr-t 2 i.dudin_pro linux_users 4096 Mar 26 16:18 dir
-rw-r--r-T 1 i.dudin_pro linux_users    0 Mar 26 16:18 file
i.dudin_pro@mon-test-vm-01y:~/test$ touch file2
i.dudin_pro@mon-test-vm-01y:~/test$ mkdir dir2
i.dudin_pro@mon-test-vm-01y:~/test$ ls -l
total 8
drwxr-xr-t 2 i.dudin_pro linux_users 4096 Mar 26 16:18 dir
drwxr-xr-x 2 i.dudin_pro linux_users 4096 Mar 26 16:19 dir2
-rw-r--r-T 1 i.dudin_pro linux_users    0 Mar 26 16:18 file
-rw-r--r-- 1 i.dudin_pro linux_users    0 Mar 26 16:19 file2
i.dudin_pro@mon-test-vm-01y:~/test$ chmod a+t file2
i.dudin_pro@mon-test-vm-01y:~/test$ chmod a+t dir2
i.dudin_pro@mon-test-vm-01y:~/test$ ls -l
total 8
drwxr-xr-t 2 i.dudin_pro linux_users 4096 Mar 26 16:18 dir
drwxr-xr-t 2 i.dudin_pro linux_users 4096 Mar 26 16:19 dir2
-rw-r--r-T 1 i.dudin_pro linux_users    0 Mar 26 16:18 file
-rw-r--r-T 1 i.dudin_pro linux_users    0 Mar 26 16:19 file2

Размер буквы указывает на включенность аттрибута x

-rw-r--r-T 1 i.dudin_pro linux_users    0 Mar 26 16:21 file3
-rw-r--r-t 1 i.dudin_pro linux_users    0 Mar 26 16:22 file4
  • T — означает, что разрешения на выполнение отключены
  • t — означает, что права на выполнение включены

При установке SGID на каталог, новые файлы в каталоге будут наследовать владельца-группу по владельцу-группе каталога

i.dudin_pro@mon-test-vm-01y:~/test/a$ ls -la
total 8
drwxr-sr-x 2 i.dudin_pro www-data    4096 Mar 26 13:53 . # видим что текущая директория имеет sgid
drwxr-xr-x 3 i.dudin_pro linux_users 4096 Mar 26 13:53 ..

i.dudin_pro@mon-test-vm-01y:~/test/a$ touch file # создаем файл

i.dudin_pro@mon-test-vm-01y:~/test/a$ ls -la
total 8
drwxr-sr-x 2 i.dudin_pro www-data    4096 Mar 26 14:12 .
drwxr-xr-x 3 i.dudin_pro linux_users 4096 Mar 26 13:53 ..
-rw-r--r-- 1 i.dudin_pro www-data       0 Mar 26 14:12 file # файл унаследовал группу от папки (пользователь-создатель имеет другую группу

SUID на каталог не ставится


Кроме обычных и дополнительных аттрибутов, файлы могут наделяться скрытыми аттрибутами, обусловленными конкретной реализацией файловой системы

В случае конфликта прав между между обычными и специфическими аттрибутами, решают специфические

i.dudin_pro@mon-test-vm-01y:~/test$ sudo chattr +i file
i.dudin_pro@mon-test-vm-01y:~/test$ lsattr file
----i--------e-- file
i.dudin_pro@mon-test-vm-01y:~/test$ sudo rm file 
rm: cannot remove 'file': Operation not permitted # даже от рута не удаляется
i.dudin_pro@mon-test-vm-01y:~/test$ sudo chattr +a file
i.dudin_pro@mon-test-vm-01y:~/test$ lsattr file
-----a-------e-- file
i.dudin_pro@mon-test-vm-01y:~/test$ echo "test" > file # нельзя перезаписать
-bash: file: Operation not permitted
i.dudin_pro@mon-test-vm-01y:~/test$ echo "test" >> file # но можно дозаписать
i.dudin_pro@mon-test-vm-01y:~/test$ cat file
test

При настройке прав с помощью числовой комбинации можно использовать эти числа в качестве четвертого (самого левого) префикса

  • 0 - setuid, setgid, sticky bits не установлены
  • 1 - Установить sticky bit
  • 2 - Установить setgid bit
  • 3 - Установить setgid и sticky bits
  • 4 - Установить setuid bit
  • 5 - Установить setuid и sticky bits
  • 6 - Установить setuid и setgid bit-ы
  • 7 - setuid, setgid, sticky bits активированы

Для того чтобы программа могла быть запущена на выполнение, ОС сначала должна создать соответствующее окружение (среду выполнения) куда относятся ресурсы памяти, возможность доступа к устройствам и другие различные ресурсы
Это окружение называется процесс

Не следует отождествлять процесс и программу, потому что одна программа может породить множество процессов

Выполнение процесса заключается в точном следовании набору инструкций, который никогда не передает управление набору инструкций другого процесса
Процесс взаимодействует с разделом данных и стеком, но ему недоступны разделы данных и стеки других процессов

Чтобы процессы могли взаимодействовать между собой существует система межпроцессного взаимодействия
В нее входят сигналы, каналы, разделяемая память, семафоры, сообщения и файлы, но в остальном процессы изолированы друг от друга


Бывают системные демоны которые запускаются при инициализации ядра и нужны для работы ОС (они не имеют исполняемых файлов, их код является частью ядра)
Это разные демоны свопинга, демоны памяти, деспетчеры буферного кэша итд

Бывают просто демоны которые стртуют либо от рук пользователя либо автоматически после инициализации ядра (это разные web, ftp, ssh демоны)

Бывают прикладные процессы, они как правило интерактивные
Таким процессом является оболочка


Процессы имеют некоторые аттрибуты благодаря которым ОС может эффективно управлять ими

PID (Process ID) - уникальный в системе номер процесса позволяющий различать процессы. Новому процессу присваивается следующий свободный номер (присвоение происходит по возрастающей, т.е. чем новее процесс тем больше его pid)
Когда номера заканчиваются то новому процессу выдается минимальный из свободных (ведь при завершении процесса его pid освобождается) и все идет по второму кругу

PPID (Parent Process ID) - Pid родительского процесса
Nice Number - Относительный приоритет процесса учитываемый планировщиком при определнии очередности запуска (процессорные ресурсы распределяются исходя из приоритета выполнения который вычисляется динамически ядром и зависит в том числе от относительного приоритета)

TTY (Терминальная линия) - Терминал или псевдотерминал ассоциированный с процессом (демоны такого не имеют)

RID,EUID (Реальный и эффективный ID) - Реальный это id пользователя который запустил программу, а эффективный это id пользователя чьими правами наделен процесс. Обычно они эквивалентны, но euid можно изменить с помощью suid

RGID,EGID - То же самое что и выше но про группу


Новый процесс порождается с помощью системного вызова fork
Дочерний процесс является точной копией родительского

Дочерний отличается от родительского только pid'ом (ну и ppid'ом), все остальное (данные, инструкции, права и прочее) наследуется
Даже выполнение начнется с одного и того же момента

Далее выполняется вызов exec для загрузки кода новой программы в новый процесс и выполнения


Сигналы нужны для уведомления процессов о разных событиях
Например если процесс пытается поделить на ноль то ядро пошлет ему сигнал SIGFPE
А при нажатии Ctrl+C процесс получит сигнал SIGINT

Для отправления сигнала используется команда kill

root может слать сигналы кому угодно, а пользователь должен слать сигналы тем процессам владельцем которых он является
Должны совпадать RID/EUID процесса отправителя и процесса получателя

При получении сигнала процесс имеет три пути:

  • Игнорирование сигнала (но так нельзя, потому что дальшейшая судьба процесса непредсказуема)
  • Действие по умолчанию (обычно это завершение)
  • Можно перехватить сигнал и самостоятельно обработать его. Например перехватив сигнал SIGINT процесс может удалить свои временные файлы и произвести прочие подготовительные работы перед смертью

Некоторые сигналы нельзя перехватить (SIGKILL, SIGSTOP)

Но иногда и после неперехватываемых сигналов процесс может не завершиться:

  • Зомби (зомби это запись в таблице процессов, самого процесса уже нет. Поэтому в малых количествах они не представляют опасности, но опасно когда их много потому что они могут заполнить всю таблицу процессов)
  • Процессы ожидающие недоступные ресурсы (можно послать SIGINT,SIGQUIT, должно помочь)
  • Процессы ожидающие завершения операции с устройством (перемотка ленты)

Сигналы могут иметь специфичные для приложения значения
Например SIGHUP для named заставит его перечитать базу с диска


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

Существует два типа специальных файлов устройств

  • Файлы блочных устройств
  • Файлы символьных устройств

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

Вместо размера у специальных файлов устройств выводится мажор и минор
Эти числа указывают на драйвер (мажор) и конкретное устройство обслуживаемое этим драйвером (минор) (минор передается драйверу который находится по мажору)


Пользователь тоже имеет аттрибуты
Их можно увидеть в файле /etc/passwd

[19:39:16] vandud@macbook: vacuum-on-db-mon [0]$ grep -vE '^#' /etc/passwd | head
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
daemon:*:1:1:System Services:/var/root:/usr/bin/false
...
  1. name - логин пользователя
  2. passwd - закодированный пароль, обычно на месте этого аттрибута стоит 'x', а сам пароль хранится в /etc/shadow, в случае если в этом месте стоит '*' то пользователь не сможет зайти в систему, обычно такой пароль имеют псевдоюзеры
  3. UID - user id
  4. GID - id первичной группы пользователя
  5. comment - обычно это реальное имя пользователя
  6. homedir - хомяк
  7. shell - шелл

root имеет uid=0
root - это только имя, неограниченные полномочия имеет пользователь с uid=0 (то есть можно сменить root на что-то свое)

Аналогично с группой root или wheel которая имеет GID=0

Сегодня нормой считается создание персональной группы для каждого пользователя
Таким образом исключается случайное превышение полномочий за счет групповых прав


При включении терминала активируется программа getty, она является сервером терминального доступа и запускает программу login, которая после успешной аутентификации запускает программу из последнего столбца /etc/passwd (оболочку)

Начальное окружение устанавливается программой login
А именно:

  • HOME - 6 поле из passwd
  • LOGNAME - 1 поле из passwd
  • PATH
  • SHELL - 7 поле из passwd
  • MAIL - /var/mail/LOGNAME
  • TZ - определено системой

Экспорт переменных

[21:28:33] vandud@macbook: ~ [0]$ echo $TEST

[21:28:43] vandud@macbook: ~ [0]$ TEST=test
[21:28:48] vandud@macbook: ~ [0]$ echo $TEST
test
[21:28:51] vandud@macbook: ~ [0]$ bash -c 'echo $TEST'

[21:28:59] vandud@macbook: ~ [0]$ export TEST=test
[21:29:08] vandud@macbook: ~ [0]$ bash -c 'echo $TEST'
test
[21:29:11] vandud@macbook: ~ [0]$

Просто определнные переменные являются внутренними текущего экземпляра оболочки и не наследуются порожденными процессами
Чтобы они начали наследоваться нужно обозначить их как экспортируемые


Любая команда в оболочке относится к одной из трех категорий:

  • Встроенные функции (builtins)
  • Функции определенные пользователем
  • Внешние программы и утилиты

Встроенные функции выполняются быстрее всего, потому что для их выполнения не требутся порождать новый процесс (новый процесс это дорого)


В bash есть функция exec
Она делает то что описано выше про системеный вызов exec

[14:22:09] vandud@macbook: ~ [0]$ ssh mon-test-vm-01y.g01.i-free.ru
i.dudin_pro@mon-test-vm-01y:~$ exec ps ### Вызываю ps через exec
  PID TTY          TIME CMD
 2268 pts/0    00:00:00 ps ### Видим только ps
Connection to mon-test-vm-01y.g01.i-free.ru closed. ### И вылетаем (потому что ps завершился, а bash'a у нас нет)

[14:22:23] vandud@macbook: ~ [0]$ ssh mon-test-vm-01y.g01.i-free.ru
i.dudin_pro@mon-test-vm-01y:~$ ps ### То же самое но без exec
  PID TTY          TIME CMD
 2295 pts/0    00:00:00 bash ### bash есть
 2310 pts/0    00:00:00 ps
i.dudin_pro@mon-test-vm-01y:~$ ### И мы не вылетаем

У bash есть функция для определения действий которые будут выполнены при получении bash'ем сигналов

i.dudin_pro@mon-test-vm-01y:~$ trap 'echo signal recieved' 14
i.dudin_pro@mon-test-vm-01y:~$ ps
  PID TTY          TIME CMD
 3687 pts/1    00:00:00 bash
 3705 pts/1    00:00:00 ps
i.dudin_pro@mon-test-vm-01y:~$ kill -14 3687
signal recieved
i.dudin_pro@mon-test-vm-01y:~$

Функции в bash не особо отличаются от скриптов, в них так же предаются аргументы и внутри перечисляются команды
Но функции располагаются внутри памяти и поэтому работают быстрее

No Comments
Back to top