Пользователи системы


Удаление файлов и каталогов



страница14/42
Дата01.12.2017
Размер5.38 Mb.
ТипПрограмма
1   ...   10   11   12   13   14   15   16   17   ...   42

Удаление файлов и каталогов


В Linux для удаления файлов предназначена утилита rm (сокращение от англ. "remove" - "удалять"):

[methody@localhost methody]$ rm examples/text

[methody@localhost methody]$ ls -l text-hardlink

-rw-r--r-- 1 methody methody 653 Сен 30 10:04 text-hardlink

[methody@localhost methody]$ rm text-hardlink

[methody@localhost methody]$ ls -l text-hardlink

ls: text-hardlink: No such file or directory

Пример 4.16. Удаление файла (html, txt)

Разобравшись в ссылках, Мефодий решил удалить файл text в каталогеexamples. После этого файл text-hardlink в домашнем каталоге Мефодия, который является жесткой ссылкой на удаленный файл text, продолжает благополучно существовать. Единственное отличие, которое заметил Мефодий - количество жестких ссылок на этот файл теперь уменьшилось с "2" до "1" - действительно, text-hardlink - теперь единственное имя этого файла. Получается, что Мефодий удалил только одно из имен этого файла (жесткую ссылку) - сам же файл остался нетронутым.

Однако если Мефодий удалит и жесткую ссылку text-hardlink, у этого файла больше не останется ни одного имени, он станет недоступным пользователю файловой системы и будет уничтожен.

Утилита rm предназначена именно для удаления жестких ссылок, а не самих файлов. В Linux, чтобы полностью удалить файл, требуется последовательно удалить все жесткие ссылки на него. При этом все жесткие ссылки на файл (его имена) равноправны - среди них нет "главной", с исчезновением которой исчезнет файл. Пока есть хоть одна ссылка, файл продолжает существовать. Впрочем, у большинства файлов в Linux есть только одно имя (однажесткая ссылка на файл), поэтому команда rm имя файла в большинстве случаев успешно удаляет файл.

Как уже говорилось, символьные ссылки - это отдельные файлы, поэтому после того, как Мефодий удалил файлtext, text-symlink, который ссылался на этот файл, продолжает существовать, однако теперь это - "битая ссылка", поэтому его также можно удалить командой rm.

Мефодий решил создать каталог для разных упражнений - test, а потом решил обойтись одним каталогомexamples. Однако команда rm не сработала, заявив, что test - это каталог:

[methody@localhost methody]$ mkdir test

[methody@localhost methody]$ rm test

rm: невозможно удалить `test': Is a directory

[methody@localhost methody]$ rmdir test

[methody@localhost methody]$

Пример 4.17. Удаление каталога (html, txt)

Для удаления каталогов предназначена другая утилита - rmdir (от англ. "remove directory"). Впрочем, rmdirсогласится удалить каталог только в том случае, если он пуст: в нем нет никаких файлов и подкаталогов. Удалитькаталог вместе со всем его содержимым можно командой rm с ключом "-r" (recursive). Команда rm -r каталог - очень удобный способ потерять в одночасье все файлы: она рекурсивно1) обходит весь каталог, удаляя все, что попадется: файлы, подкаталоги, символьные ссылки... а ключ "-f" (force) делает ее работу еще неотвратимее, так как подавляет запросы вида "удалить защищенный от записи файл", так что rm работает безмолвно и безостановочно.



Помните: если вы удалили файл, значит, он уже не нужен, и не подлежит восстановлению!

В Linux не предусмотрено процедуры восстановления удаленных файлов и каталогов. Поэтому стоит быть оченьвнимательным, отдавая команду rm и, тем более, rm -r: нет никакой гарантии, что случайно удаленные данные удастся восстановить. Узнав об этом, Мефодий не огорчился, но подумал, что впредь будет удалять толькодействительно ненужные файлы, а все сомнительное - перемещать с помощью mv в подкаталог ~/tmp, где оно не будет мешать, и где можно периодически наводить порядок.


Процессы


Как уже упоминалось в лекции 1, загрузка Linux завершается тем, что на всех виртуальных консолях (на самом деле – на всех терминалах системы), предназначенных для работы пользователей, запускается программа getty. Программа выводит приглашение и ожидает активности пользователя, который может захотеть работать именно на этом терминале. Введенное входное имя getty передает программе login, которая вводит пароль и определяет, разрешено ли работать в системе с этим входным именем и этим паролем. Если login приходит к выводу, что работать можно, она запускает стартовый командный интерпретатор, посредством которого пользователь и управляет системой.

Выполняющаяся программа называется в Linux процессом. Все процессысистема регистрирует в таблице процессов, присваивая каждому уникальный номер – идентификатор процесса (process identificator, PID). Манипулируя процессами, система имеет дело именно с ихидентификаторами, другого способа отличить один процесс от другого, по большому счету, нет. Для просмотра своих процессов можно воспользоваться утилитой ps ("process status"):

[methody@localhost methody]$ ps -f

UID PID PPID C STIME TTY TIME CMD

methody 3590 1850 0 13:58 tty3 00:00:00 -bash

methody 3624 3590 0 14:01 tty3 00:00:00 ps -f



Пример 5.1. Просмотр таблицы собственных процессов (html, txt)

Здесь Мефодий вызвал ps с ключом "-f" ("full"), чтобы добыть побольше информации. Представлены оба принадлежащих ему процессастартовый командный интерпретатор, bash, и выполняющийся ps. Оба процессазапущены с терминала tty3 (третьей системной консоли) и имеют идентификаторы 3590 и 3624 соответственно. В поле PPID ("parent process identificator") указан идентификатор родительского процесса, т. е. процесса,породившего данный. Для ps это – bash, а для bash, очевидно, login, так как именно он запускает стартовый shell. В выдаче не оказалось строки для этого login, равно как и для большинства других процессов системы, так как они не принадлежат пользователю methody.



Процесс - выполняющаяся программа в Linux. Каждый процесс имеет уникальный идентификатор процессаPID.Процессы получают доступ к ресурсам системы (оперативной памяти, файлам, внешним устройствам и т. п.) и могут изменять их содержимое. Доступ регулируется с помощью идентификатора пользователя и идентификатора группы, которые система присваивает каждому процессу.

Запуск дочерних процессов


Запуск одного процесса вместо другого организован в Linux с помощью системного вызова exec(). Старыйпроцесс из памяти удаляется навсегда, вместо него загружается новый, при этом настройка окружения не меняется, даже PID остается прежним. Вернуться к выполнению старого процесса невозможно, разве что запустить его снова с помощью того же exec() (от "execute" – "исполнить"). Кстати, имя файла (программы), из которого запускается процесс, и собственное имя процесса (в таблице процессов) могут и не совпадать. Собственное имя процесса – это такой же параметр командной строки, как и те, что передаются ему пользователем: для exec() требуется и путь к файлу, и полная командная строка, нулевой (стартовый) элемент которой – как раз название команды1).

Вот откуда "-" в начале имени стартового командного интерпретатора (-bash): его "подсунула" программа login, чтобы была возможность отличать его от других запущенных тем же пользователем оболочек.

Для работы командного интерпретатора одного exec() недостаточно. В самом деле, shell не просто запускает утилиту, а дожидается ее завершения, обрабатывает результаты ее работы и продолжает диалог с пользователем.Для этого в Linux служит системный вызов fork() ("вилка, развилка"), применение которого приводит к возникновению еще одного, дочернегопроцесса – точной копии породившего его родительскогоДочерний процесс ничем не отличается от родительского: имеет такое же окружение, те же стандартный ввод истандартный вывод, одинаковое содержимое памяти и продолжает работу с той же самой точки (возврат изfork()). Отличий два: во-первых, эти процессы имеют разные PID, под которыми они зарегистрированы в таблице процессов, а во-вторых, различается возвращаемое значение fork(): родительский процесс получает в качестве результата fork() идентификатор процесса-потомка, а процесс-потомок получает "0".

Дальнейшие действия shell при запуске какой-либо программы очевидны. Shell-потомок немедленно вызывает эту программу с помощью exec(), а shell-родитель дожидается завершения работы процесса-потомка (PID которого ему известен) с помощью еще одного системного вызова, wait(). Дождавшись и проанализировав результат команды, shell продолжает работу:

[methody@localhost methody]$ cat > loop

while true; do true; done

^D

[methody@localhost methody]$ sh loop



^C

[methody@localhost methody]$



Пример 5.2. Создание бесконечно выполняющегося сценария (html, txt)

По совету Гуревича Мефодий создал сценарий для sh (или bash, на таком уровне их команды совпадают), который ничего не делает. Точнее было бы сказать, что этот сценарий делает ничего, бесконечно повторяя в цикле команду, вся работа которой состоит в том, что она завершается без ошибок (в лекции 7 говорится о том, что "> файл" в командной строке просто перенаправляет стандартный вывод команды в файл). Запустив этот сценарий с помощью команды вида sh имя_сценария, Мефодий ничего не увидел, но услышал, как загудел вентилятор охлаждения центрального процессора: машина трудилась! Управляющий символ "^C", как обычно, привел к завершению активного процесса, и командный интерпретатор продолжил работу.

Если бы в описанной выше ситуации родительский процесс не ждал, пока дочерний завершится, а сразу продолжал работать, получилось бы, что оба процесса выполняются параллельно: пока запущенный процесс что-то делает, пользователь продолжает командовать оболочкой. Для того чтобы запустить процесс параллельно, в shell достаточно добавить "&" в конец командной строки:

[methody@localhost methody]$ sh loop&

[1] 3634

[methody@localhost methody]$ ps -f

UID PID PPID C STIME TTY TIME CMD

methody 3590 1850 0 13:58 tty3 00:00:00 -bash

methody 3634 3590 99 14:03 tty3 00:00:02 sh loop

methody 3635 3590 0 14:03 tty3 00:00:00 ps -f



Пример 5.3. Запуск фонового процесса (html, txt)

В результате стартовый командный интерпретатор (PID 3590) оказался родителем сразу двух процессов: sh, выполняющего сценарий loop, и ps.



Процесс, запускаемый параллельно, называется фоновым (background). Фоновые процессы не имеют возможности вводить данные с того же терминала, что и породивший их shell (только из файла), зато выводитьданные на этот терминал могут (правда, когда на одном и том же терминале вперемешку появляются сообщения от нескольких фоновых процессов, начинается неразбериха). При каждом терминале в каждый момент времени может быть не больше одного активного (foreground) процесса, которому разрешено вводить данные с этого терминала. На время, пока команда (например, cat) работает в активном режиме, породивший ее командный интерпретатор "уходит в фон", и там, в фоне, выполняет свой wait().

активный процесс, foreground process - процесс, имеющий возможность вводить данные с терминала..

Фоновый процесс, background process - процесс, не имеющий возможности вводить данные с терминала. Пользователь может запустить любое, но не превосходящее заранее заданное в системе, число фоновых процессов.

Стоит заметить, что параллельность работы процессов в Linux – дискретная. Здесь и сейчас выполняться может столько процессов, сколько центральных процессоров есть в компьютере (например, один). Дав этому одномупроцессу немного поработать, система запоминает все, что необходимо ему для работы, приостанавливает его, и запускает следующий процесс, потом следующий и так далее. Возникает очередь процессов, ожидающих выполнения. Только что поработавший процесс помещается в конец этой очереди, а следующий выбирается из ее начала. Когда очередь вновь доходит до того, первого процесса, система вспоминает необходимые для его выполнения данные (они называются контекстом процесса), и он продолжает работать как ни в чем не бывало. Такая схема разделения времени между процессами называется псевдопараллелизмом.

В выдаче ps, которую получил Мефодий, можно заметить, что PID стартовой оболочки равен 3590, а PIDзапущенных из-под него команд (одной фоновой и одной активной) – 3634 и 3635. Это значит, что за время, прошедшее с момента входа Мефодия в систему до момента запуска sh loop&, в системе было запущено еще3634-3590=44 процесса. Что ж, в Linux могут одновременно работать несколько пользователей, да и самой системе иногда случается запустить какую-нибудь утилиту (например, выполняя действия по расписанию). А вот sh и psполучили соседние PID, значит, пока Мефодий нажимал Enter и набирал ps -f, никаких других процессов не запускалось.

В действительности далеко не всем процессам, зарегистрированным в системе, на самом деле необходимо давать поработать наравне с другими. Большинству процессов работать прямо сейчас не нужно: они ожидают какого-нибудь события, которое им необходимо обработать. Чаще всего процессы ждут завершения операции ввода-вывода. Чтобы посмотреть, как потребляются ресурсы системы, можно использовать утилиту top. Но сначала Мефодий решил запустить еще один бесконечный сценарий (ему было интересно, как два процесса конкурируют за ресурсы):

[methody@localhost methody]$ bash loop&

[2] 3639


[methody@localhost methody]$ top

14:06:50 up 3:41, 5 users, load average: 1,31, 0,76, 0,42

4 processes: 1 sleeping, 3 running, 0 zombie, 0 stopped

CPU states: 99,4% user, 0,5% system, 0,0% nice, 0,0% iowait, 0,0% idle

Mem: 514604k av, 310620k used, 203984k free, 0k shrd, 47996k buff

117560k active, 148388k inactive

Swap: 1048280k av, 0k used, 1048280k free 184340k cached

PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND

3639 methody 20 0 1260 1260 1044 R 50,3 0,2 0:12 bash

3634 methody 18 0 980 980 844 R 49,1 0,1 3:06 sh

3641 methody 9 0 1060 1060 872 R 0,1 0,2 0:00 top

3590 methody 9 0 1652 1652 1264 S 0,0 0,3 0:00 bash



Пример 5.4. Разделение времени между процессами (html, txt)

Оказалось, что дерутся даже не два процесса, а три: sh (первый из запущенных интерпретаторов loop), bash(второй) и сам top. Правда, по сведениям из поля %CPU, львиную долю процессорного времени отобрали sh и bash(они без устали вычисляют!), а top довольствуется десятой долей процента (а то и меньшей: ошибки округления). Стартовый bash вообще не хочет работать, он спит (значение "S", Sleep, поля STAT, status): ждет завершенияактивного процесса, top.

Увидев такое разнообразие информации, Мефодий кинулся читать руководство по top, однако скоро понял, что без знания архитектуры Linux большая его часть не имеет смысла. Впрочем, некоторая часть все же понятна: объем оперативной памяти (всей, используемой и свободной), время работы машины, объем памяти, занимаемойпроцессами, и т. п.

Последний процесс, запущенный из оболочки в фоне, можно из этой оболочки сделать активным при помощи команды fg ("foreground" – "передний план"):

[methody@localhost methody]$ fg

bash loop

^C

Пример 5.5. Перевод фонового процесса в активное состояние с помощью команды fg (foreground) (html, txt)

Услужливый bash даже написал командную строку, которой был запущен этот процесс: "bash loop". Мефодий решил "убить" его с помощью управляющего символа "^C". Теперь последним запущенным в фоне процессом сталsh, выполняющий сценарий loop.


Сигналы


Чтобы завершить работу фонового процесса с помощью "^C", Мефодию пришлось сначала сделать его активным. Это не всегда возможно и не всегда удобно. На самом деле, "^C" – это не волшебная кнопка-убийца, а предварительно установленный символ (с ascii-кодом 3), при получении которого с терминала Linux передаст активному процессу сигнал 2 (по имени INT, от "interrupt" – "прервать").

Сигнал – это способность процессов обмениваться стандартными короткими сообщениями непосредственно с помощью системы. Сообщение-сигнал не содержит никакой информации, кроме номера сигнала (для удобства вместо номера можно использовать предопределенное системой имя). Для того чтобы передать сигналпроцессу достаточно задействоватьсистемный вызов kill(), а для того чтобы принять сигнал, не нужно ничего. Если процессу необходимо как-то по-особенному реагировать насигнал, он может зарегистрировать обработчик, а если обработчика нет, за него отреагирует система. Как правило, это приводит к немедленному завершению процесса, получившего сигнал. Обработчик сигналазапускается асинхронно, немедленно после получения сигнала, что быпроцесс в это время ни делал.

Сигнал - короткое сообщение, посылаемое системой или процессом другомупроцессу. Обрабатывается асинхронно специальной подпрограммой-обработчиком. Если процесс не обрабатывает сигнал самостоятельно, это делает система.

Два сигнала – 9 (KILL) и 19 (STOP) – всегда обрабатывает система. Первый из них нужен для того, чтобы убитьпроцесс наверняка (отсюда и название). Сигнал STOP приостанавливает процесс: в таком состоянии процессне удаляется из таблицы процессов, но и не выполняется до тех пор, пока не получит сигнал 18 (CONT) – после чего продолжит работу. В Linux сигнал STOP можно передать активному процессу с помощью управляющего символа "^Z":

[methody@localhost methody]$ sh loop

^Z

[1]+ Stopped sh loop



[methody@localhost methody]$ bg

[1]+ sh loop &

[methody@localhost methody]$ fg

sh loop


^C

[methody@localhost methody]$



Пример 5.6. Перевод процесса в фон с помощью "^Z" и bg (html, txt)

Мефодий сначала запустил вечный цикл в качестве активного процесса, затем передал ему сигнал STOP с помощью "^Z", после чего дал команду bg (back ground), запускающую в фоне последний остановленный процесс. Затем он снова перевел этот процесс в активный режим, и, наконец, убил его.

Передавать сигналы из командной строки можно любым процессам с помощью команды kill -сигнал PID или просто kill PID, которая передает сигнал 15 (TERM):

[methody@localhost methody]$ sh

sh-2.05b$ sh loop & bash loop &

[1] 3652


[2] 3653

sh-2.05b$ ps -fH

UID PID PPID C STIME TTY TIME CMD

methody 3590 1850 0 13:58 tty3 00:00:00 -bash

methody 3634 3590 87 14:03 tty3 00:14:18 sh loop

methody 3651 3590 0 14:19 tty3 00:00:00 sh

methody 3652 3651 34 14:19 tty3 00:00:01 sh loop

methody 3653 3651 35 14:19 tty3 00:00:01 bash loop

methody 3654 3651 0 14:19 tty3 00:00:00 ps -fH

Пример 5.7. Запуск множества фоновых процессов (html, txt)

Мефодий решил запустить несколько процессов, а потом выборочно поубивать их. Для этого он, вдобавок к уже висящему в фоне sh loop, запустил в качестве активного процесса новый командный интерпретатор, sh (при этом изменилось приглашение командной строки). Из этого sh он запустил в фоне еще один sh loop и новый bash loop. Сделал он это одной командной строкой (при этом команды разделяются символом "&", т. е. "И"; выходит, что запускается и та, и другая команда). В ps он использовал новый ключ – "-H" ("Hierarchy", "иерархия"), который добавляет в выдачу ps отступы, показывающие отношения "родитель–потомок" между процессами:

sh-2.05b$ kill 3634

[1]+ Terminated sh loop

sh-2.05b$ ps -fH

UID PID PPID C STIME TTY TIME CMD

methody 3590 1850 0 13:58 tty3 00:00:00 -bash

methody 3651 3590 0 14:19 tty3 00:00:00 sh

methody 3652 3651 34 14:19 tty3 00:01:10 sh loop

methody 3653 3651 34 14:19 tty3 00:01:10 bash loop

methody 3658 3651 0 14:23 tty3 00:00:00 ps -fH

Пример 5.8. Принудительное завершение процесса с помощью kill (html, txt)

Мефодий принялся убивать! Для начала он остановил работу давно запущенного sh, выполнявшего сценарий с вечным циклом (PID 3634). Как видно из предыдущего примера, этот процесс за 16 минут работы системы "съел" не менее 14 минут процессорного времени, и конечно, ничего полезного не сделал. Сигнал о том, что процесс-потомок "умер", дошел до обработчика в стартовом bash (PID 3590), и на терминал было выведено сообщение "[1]+ Terminated sh loop", после чего стартовый bash продолжил ждать завершения активного процесса – sh(PID 3651):

sh-2.05b$ exit

[methody@localhost methody]$ ps -fH

UID PID PPID C STIME TTY TIME CMD

methody 3590 1850 0 15:17 tty3 00:00:00 -bash

methody 3663 3590 0 15:23 tty3 00:00:00 ps -fH

methody 3652 1 42 15:22 tty3 00:00:38 bash loop

methody 3653 1 42 15:22 tty3 00:00:40 sh loop

[methody@localhost methody]$ kill -HUP 3652 3653

[methody@localhost methody]$ ps

PID TTY TIME CMD

3590 tty3 00:00:00 bash

3664 tty3 00:00:00 ps



Пример 5.9. Завершение процесса естественным путем с помощью сигнала "Hang Up" (html, txt)

Ждать ему оставалось недолго. Этот sh завершился естественным путем, от команды exit, оставив после себя двух "детей-сирот" (PID 3652 и 3653), которые тотчас же усыновил "отец всех процессов" – init (PID 1). Когда Мефодий расправился и с ними – с помощью сигнала 1 (HUP, то есть "Hang UP", "повесить"1)) – некому было даже сообщить об их кончине (если бы процесс-родитель был жив, на связанный с ним терминал вывелось бы что-нибудь вроде "[1]+ Hangup sh loop").





Поделитесь с Вашими друзьями:
1   ...   10   11   12   13   14   15   16   17   ...   42


База данных защищена авторским правом ©vossta.ru 2019
обратиться к администрации

    Главная страница