Шеллы что это в программировании
Интерпретатор командной строки, или shell (shell — оболочка) — эта та программа, которая принимает команды от пользователя и исполняет их.
- Взаимодействие с пользователем (редактирование командной строки, история команд и т.д.).
- Обработка (расширение) шаблонов имен (» * «, » ? » и т.д.).
- Перенаправление ввода/вывода команд.
- Управление заданиями.
Кроме того, shell — это специализированный язык программирования, в котором есть переменные, конструкции while, if, for и т.д., функции и много чего еще. Он позволяет писать как несложные сценарии для автоматизации повседневных задач, так и довольно сложные программы (например, запуск и останов большинства Unix’ов производятся сценариями на языке shell).
Хотя работа непосредственно в командной строке (а не в оболочке типа NortonCommander или какой-нибудь оконной) на первый взгляд не столь удобна, она обеспечивает более удобный доступ к таким функциям, как перенаправление ввода/вывода и управление заданиями — оболочки типа Midnight Commander в этом случае будут только мешать.
Shell — это не одна конкретная программа. Исторически существует несколько подвидов оболочек; «генеалогическое древо» представлено на Рис.1.
Рис.1: семейство интерпретаторов командной строки |
Не вдаваясь в подробности истории (краткое описание можно найти в разделе 3.10 книги «Unix: универсальная среда программирования» Кернигана и Пайка), стоит лишь заметить, что csh и tcsh не в полной мере реализуют командный язык sh, а zsh, являясь самой последней разработкой, умеет все, что и любой другой подвид, и плюс много чего еще.
Кроме того, поскольку командный интерпретатор имеет десятки параметров для настройки, не следует удивляться, увидев, что некая знакомая оболочка на другом компьютере выглядит и ведет себя по другому.
Изложение в данном разделе основано на zsh (которая и используется на практических занятиях), но большая часть описанного верно и для других оболочек.
Что такое bash / shell
И то, и другое — интерпретаторы командной строки в линуксе. То есть если вы откроете командную строку и введете любую команду, да хоть:
cd /home
То именно интерпретатор ее расшифрует и скажет компьютеру «он хочет перейти в директорию /home». Компьютер ведь не понимает команды на русском / английском языке. Ему нужны байтики. Этим и занимается интерпретатор — переводом с «нашего» на «компьютерный» язык.
Так что «cd /home» — это shell-команда! Или bash. Смотря какой интерпретатор установлен в вашей системе. В каждой операционной системе установлен интерпретатор по умолчанию. У них есть какие-то различия, но есть и набор базовых команд, которые понимают все: cd, mv, cp, ls… (в винде эти команды немного другие)
А что такое shell-скрипт тогда? Это просто текстовый документ, внутри которого написан набор команд! Это не обязательно должны быть «сложные» команды, которые делают что-то супер-навороченное. Это любые команды, которые вы выполняете в консоли.
Например, создадим скриптик, который создаст директорию и в ней файлик:
mkdir /home/test cd /home/test touch test.txt
Так, команды записали, осталось сохранить их в файлик. Скрипты хранят в файлах с расширением .sh, поэтому назовем файл first_script.sh. Но есть нюанс — линуксу плевать на ваше расширение файла. Его может вообще не быть, и все равно скрипт останется скриптом. Почему? Потому что у любого скрипта в первой строке должен содержаться путь к интерпретатору. Например:
#!/bin/bash или #!/bin/sh
Весь файл целиком:
#!/bin/bash mkdir /home/test cd /home/test touch test.txt
И даже если у такого файла не будет расширения вовсе, его можно будет запустить как скрипт:
sh first_script # Проверяем директорию /home — там появилась папка test с файлом test.txt внутри.
Расширение .sh ставится для понимания человеком. Зашел в директорию:
— Ага, что тут у нас? Файлы sh, скрипты какие-то лежат.
Скрипты могут быть простые, а могут быть сложные. Вот, например, в одном проекте мы вначале вручную обновляли тестовые платформы. Для обновления надо:
- Остановить сервис.
- Переподложить war-файл с приложением (лежат они в директории /opt)
- Запустить сервис
Сервиса два, допустим это test и cloud. Так что шагов уже 6.
Когда обновлять вручную надоело, мы положили на все линукс машины простой скриптик:
#!/bin/bash service test stop cp test.war /opt/jboss-test/bin service test start service cloud stop cp cloud.war /opt/jboss-cloud/bin service cloud start
Собираешь приложение, подкладываешь к скриптику и запускаешь 1 команду вместо 6. Удобно! Это называется «автоматизация рутины» =)
Другой пример с того же проекта — мы делали серверное приложение. И во время установки приложения на сервере linux нужно выполнить пункты по настройке самой системы. Например, увеличить параметр max_map_count — сколько максимум памяти может использовать процесс.
Приложение в пике работы требует много памяти. Если не настроить параметр, то «тяжеловесная» задача просто упадет с ошибкой «Не хватает памяти». И если мы видим такую ошибку, то в первую очередь идем проверять настройки системы.
Вообще, если вы отдаете установку приложения на откуп «чужим» админам, лучше потом проверять — а всё ли настроено верно? Конечно, обычно на production (машина, с которой работают реальные пользователи) настраивают всё внимательно, это на тестовых стендах могут что-то пропустить. Но лучше перебдеть!
Мы написали скрипт по проверке настройки окружения (символ «#» в начале строки означает, что это комментарий):
#!/bin/sh # # check sysctl # if [ -f /proc/sys/vm/max_map_count ] && [ $(cat /proc/sys/vm/max_map_count) -ge 16777216 ]; then echo "vm.max_map_count: ok" else echo "vm.max_map_count: failed" fi if [ -f /proc/sys/vm/overcommit_memory ] && [ $(cat /proc/sys/vm/overcommit_memory) -eq 2 ]; then echo "vm.overcommit_memory: ok" else echo "vm.overcommit_memory: failed" fi if [ -f /proc/sys/vm/overcommit_ratio ] && [ $(cat /proc/sys/vm/overcommit_ratio) -eq 100 ]; then echo "vm.overcommit_ratio: ok" else echo "vm.overcommit_ratio: failed" fi if [ -f /proc/sys/vm/swappiness ] && [ $(cat /proc/sys/vm/swappiness) -le 10 ]; then echo "vm.swappiness: ok" else echo "vm.swappiness: failed" fi
В итоге админы настраивают окружение, а потом мы даем им скрипт, просим запустить его и прислать результаты. Я запустила скрипт на «голой» системе, где, разумеется, параметры настроены не были, и вот ответ:
Видим, что все проверки провалились, статус failed. Если и от админов приходит похожая картина, направляем их в документацию по настройке системы. Если к нам приходят с проблемой падения из-за нехватки памяти, снова просим выполнить скрипт. Так проще локализовать ошибку: это в приложении косяк, или окружение настроено плохо?
Просить других людей выполнить 10 команд не очень хорошо. Потому что часть команд может «потеряться» при выполнении — плохо скопировал, забыл выполнить проверку, которую дали сообщением позже. Гораздо проще сделать 1 скрипт и попросить выполнить именно его.
Когда надо писать скрипт?
- Когда надо выполнить больше 3 команд за раз — проще выполнить одну, запустить скрипт.
- Когда одну и ту же команду надо выполнять чаще 3 раз — лучше автоматизировать эту работу.
По сути своей, bash-скрипты — это та же автоматизация. А когда нужна автоматизация? Когда мы хотим избавиться от рутины, от постоянного выполнения одного и того же действия вручную. Повторяете одно и то же каждый день / неделю? Напишите скрипт. Даже если он на 2-3 строчки будет, это правда удобнее. Поверьте, сама делала небольшие скрипты =)
См также по bash:
Основы BASH. Часть 1 (Хабр) — цикл статей о том, как писать скрипты
См также другие статьи из цикла «Что такое. »:
Шеллы что это в программировании
Shell: что это такое и зачем он нужен
Интерпретатор командной строки, или shell (shell — оболочка) — эта та программа, которая принимает команды от пользователя и исполняет их.
- Взаимодействие с пользователем (редактирование командной строки, история команд и т.д.).
- Обработка (расширение) шаблонов имен (» * «, » ? » и т.д.).
- Перенаправление ввода/вывода команд.
- Управление заданиями.
Кроме того, shell — это специализированный язык программирования, в котором есть переменные, конструкции while, if, for и т.д., функции и много чего еще. Он позволяет писать как несложные сценарии для автоматизации повседневных задач, так и довольно сложные программы (например, запуск и останов большинства Unix’ов производятся сценариями на языке shell).
Хотя работа непосредственно в командной строке (а не в оболочке типа NortonCommander или какой-нибудь оконной) на первый взгляд не столь удобна, она обеспечивает более удобный доступ к таким функциям, как перенаправление ввода/вывода и управление заданиями — оболочки типа Midnight Commander в этом случае будут только мешать.
Shell — это не одна конкретная программа. Исторически существует несколько подвидов оболочек; «генеалогическое древо» представлено на Рис.1.
Рис.1: семейство интерпретаторов командной строки |
Не вдаваясь в подробности истории (краткое описание можно найти в разделе 3.10 книги «Unix: универсальная среда программирования» Кернигана и Пайка), стоит лишь заметить, что csh и tcsh не в полной мере реализуют командный язык sh, а zsh, являясь самой последней разработкой, умеет все, что и любой другой подвид, и плюс много чего еще.
Кроме того, поскольку командный интерпретатор имеет десятки параметров для настройки, не следует удивляться, увидев, что некая знакомая оболочка на другом компьютере выглядит и ведет себя по другому.
Изложение в данном разделе основано на zsh (которая и используется на практических занятиях), но большая часть описанного верно и для других оболочек.
Перенаправление ввода/вывода file», «less file» 2. «cp src1 src2 dst» — ошибка, «cat src1 src2 >dst» — ok 3. «cat src >>dst» 4. «ls -l | less» 5. «sort log» — ? : stderr! «ls -l >log 2>errlog», 2>/dev/null, 2>&1 7. zsh: «ls >file1 >file2» —- 1.5 «ls -l >file» — «file» войдет в список от ls! —>
Представим себе ситуацию: хочется посмотреть листинг директории /bin (в которой лежат многие программы). Выполняем команду » ls -l /bin » и. Результат в экран не помещается. А ведь бывают директории еще большего объема. Что делать?
Большинство команд выводят информацию на терминал, а некоторые (например, текстовый редактор) вводят данные с терминала. В Unix есть почти универсальное правило: терминал может быть заменен для ввода, вывода или и того, и другого, на файл .
Так, чтобы сохранить вывод нашей команды в файл, надо написать:
bobby:~% ls -l /bin >filelist bobby:~%
При этом весь вывод команды ls будет вместо терминала отправлен в файл. Символ » > » означает, что выходной поток должен быть помещен в указанный далее файл, а не выведен на терминал. Если в файле что-то было, то старое содержимое будет стерто.
Получив таким образом список файлов, его можно просмотреть командой less .
Еще один пример: можно слить содержимое нескольких файлов в один файл, «перехватив» выходной поток команды cat и отправив его в файл:
bobby:~% cat file1 file2 file3 >all bobby:~% _
Сделать то же самое при помощи команды cp нельзя:
bobby:~% cp file1 file2 file3 all cp: copying multiple files, but last argument (all) is not a directory Try `cp --help' for more information. bobby:~% _
Символ » >> » действует подобно » > «, но указывает на необходимость добавить выходной поток к концу файла, вместо того, чтобы стереть старое содержимое. Например:
bobby:~% cat file1 >all bobby:~% cat file2 file3 >>all bobby:~% _
Первая команда cat скопирует содержимое file1 в all , а вторая — допишет к нему содержимое file2 и file3 .
Использование » >> » очень удобно, если есть некий «долгоживущий» файл (например, протокол каких-то действий или результатов), к которому иногда надо дописывать данные в конец. Просто указать » >> » с какой-нибудь командой обычно намного быстрее, чем загружать файл в текстовый редактор и что-то дописывать.
Теперь вернемся к нашему первому примеру: как посмотреть листинг большой директории. Мы отправили вывод команды ls в файл, а потом запустили less для его просмотра. Сам же временный файл не имеет никакого смысла — потом он больше не нужен.
Можно обойтись без временного файла, воспользовавшись конвейером:
bobby:~% ls -l /bin | less
Символ » | » означает, что надо взять выходной поток от первой команды, и отправить его на входной поток второй.
Большинство команд, выдающих информацию из файла на экран ( cat, more, less ) устроены так, что они будут читать входной поток, если не указан никакой файл — вот почему less показывает то, что ему «пришло» от ls .
Можно заставить команду читать вместо терминала не только выходной поток другой команды, но и обычный файл. Это делается при помощи оператора » < ", который указывает, что вместо терминала надо брать входной поток из указанного далее файла. Пример (команда " sort " построчно сортирует входные данные):
bobby:~% cat proverbs What is worth doing, is worth doing well. Art is long, life is short. History repeats itself. Dead men tell no tales. _______________________ bobby:~% sort Art is long, life is short. Dead men tell no tales. History repeats itself. What is worth doing, is worth doing well. _______________________ bobby:~% _
Что будет, если мы попросим ls показать файлы, которых нет?
bobby:~% ls -l file1 file2 file10 file11 /bin/ls: file10: No such file or directory /bin/ls: file11: No such file or directory -rw-r--r-- 1 ivanov lab5 76 Feb 21 13:23 file1 -rw-r--r-- 1 ivanov lab5 32 Feb 21 13:23 file2 bobby:~% _
Файлы которые есть, ls покажет, а про остальные скажет, что их нет. А теперь перенаправим вывод ls в файл:
bobby:~% ls -l file1 file2 file10 file11 >filelist /bin/ls: file10: No such file or directory /bin/ls: file11: No such file or directory bobby:~% _
В чем же дело?! Казалось бы, на экране ничего не должно появиться.
А дело в том, что кроме выходного потока есть еще поток сообщений об ошибках , и «культурно» написанные программы все «ругательства» отправляют туда. Чтобы перенаправить в файл поток сообщений об ошибках (обычно его сокращенно называют stderr), надо перед символом » > » указать номер потока — 2. Пример:
bobby:~% ls -l file1 file2 file10 file11 >filelist 2>errs bobby:~% cat filelist -rw-r--r-- 1 ivanov lab5 76 Feb 21 13:23 file1 -rw-r--r-- 1 ivanov lab5 32 Feb 21 13:23 file2 bobby:~% cat errs /bin/ls: file10: No such file or directory /bin/ls: file11: No such file or directory bobby:~% _
С потоком stderr обычно требуется сделать одну из трех вещей: перенаправить его туда же, куда и выходной поток, направить в отдельный файл, или отправить «в никуда». В первом случае можно воспользоваться специальной формой оператора перенаправления вывода — » 2>&1 » («отправь второй поток (stderr) туда же, куда и первый (stdout)):
bobby:~% ls -l file1 file2 file10 file11 >filelist 2>&1 bobby:~% cat filelist /bin/ls: file10: No such file or directory /bin/ls: file11: No such file or directory -rw-r--r-- 1 ivanov lab5 76 Feb 21 13:23 file1 -rw-r--r-- 1 ivanov lab5 32 Feb 21 13:23 file2 bobby:~% _
Этот способ работает и тогда, когда стандартный вывод отправляется по конвейеру другой программе.
Во третьем же случае надо отправить stderr в «черную дыру» — файл /dev/null :
bobby:~% ls -l file1 file2 file10 file11 >filelist 2>/dev/null bobby:~% cat filelist -rw-r--r-- 1 ivanov lab5 76 Feb 21 13:23 file1 -rw-r--r-- 1 ivanov lab5 32 Feb 21 13:23 file2 bobby:~% _
Подробную информацию на эту тему можно найти в info-документации на zsh , набрав команду » info zsh redirection «.
Здесь же следует лишь заметить, что zsh обладает способностью перенаправлять вывод в несколько файлов сразу. Это бывает полезно, если хочется запустить какую-нибудь «долгоиграющую» команду так, чтобы ее вывод сохранялся в файле, но при этом отображался бы и на экране — для этого надо перенаправить вывод одновременно в файл «протокола» и в файл /dev/tty .
Часто возникает задача: надо найти, в каком файле встречается некое слово или фраза. Для этого служит команда » grep «. Она ищет «образец» в указанных файлах (или в стандартном вводе, если файлы не указаны) и печатает все строки, на которых он встречается. Пример (найти строку » no «):
bobby:~% grep no * proverbs:Dead men tell no tales. bobby:~% _
Каждая строка предваряется именем файла, в котором она найдена, и двоеточием; если указан только один файл (или стандартный ввод), то этого не делается — просто печатается найденная строка.
С ключом » -i » grep ищет, не различая маленькие/заглавные буквы:
bobby:~% grep no * errs:/bin/ls: file10: No such file or directory errs:/bin/ls: file11: No such file or directory proverbs:Dead men tell no tales. bobby:~% _
- » . » означает «любой символ».
- » * » — любое количество повторений (0 и больше) предшествующего символа.
- «^» — начало строки.
- «$» — конец строки.
- Специальное значение имеют также символы ? , [ , ] , < , >, | , + , \ .
Поскольку большинство этих символов имеют специальное значение и для оболочки, то образец следует указывать в одинарных кавычках (прямых апострофах).
Пример (найти все символьные линки в директории /etc):
bobby:~% ls -l /etc | grep '^l' lrwxrwxrwx 1 root root 21 Dec 9 20:55 initrunlvl -> ../ var/run/initrunlvl lrwxrwxrwx 1 root root 38 Dec 9 21:04 localtime -> ../u sr/share/zoneinfo/Asia/Novosibirsk lrwxrwxrwx 1 root root 11 Dec 9 20:44 rmt -> ../sbin/rm t* bobby:~% _
Здесь используется то, что для символьных линков ls первым символом строки (тип файла) выводит букву » l «.
Если результат grep слишком большой и не помещается на экран, то его можно «переправить» команде просмотра, например, less . Пример (показать список всех поддиректорий из директории /usr/lib):
bobby:~% ls -l /usr/lib | grep '^d' | less
Вообще говоря, в конвейере может участвовать сколько угодно команд. Так, команда
bobby:~% ls -l /usr/doc | grep '^d' | grep 'lib' | less
делает почти то же, что и в предыдущем примере, но отбирает только те директории, в имени которых есть «lib».
(Не стоит пытаться понять, откуда такое странное название — это длинная история.) —>
Фоновое исполнение задач
Часто бывает нужно запустить «долгоиграющую» программу, которая все равно пишет данные только в файл (например, какие-либо вычисления), или графическое приложение, которое не пользуется окном терминала. Но ведь пока программа запущена, терминал «принадлежит» ей, и им больше ни для чего нельзя пользоваться!
Unix позволяет запускать задачи в «фоновом режиме»: если в конце командной строки указать символ » & «, то после запуска команды терминал можно продолжать использовать для ввода других команд.
Пример (запустить графический калькулятор):
bobby:~% xcalc & [1] 2616 bobby:~% _
В квадратных скобках shell печатает номер задания, а за ним — номер процесса (об этом подробнее в следующем разделе).
Таким образом можно запустить в фоновом режиме несколько задач — например, калькулятор, текстовый редактор и «снежную зиму»:
bobby:~% xedit & [2] 2628 bobby:~% xsnow & [3] 2629 bobby:~% _
Посмотреть список запущенных задач можно командой » jobs «:
bobby:~% jobs [1] running xcalc [2] - running xedit [3] + running xsnow bobby:~% _
(Символы «+» и «-» означают «последняя запущенная задача» и «предпоследняя»).
Если у программы не предусмотрено способа завершить исполнение, то ее можно «убить» командой » kill «:
bobby:~% kill %3 [3] + done xsnow bobby:~% _
Символ процента и следующий за ним номер являются ссылкой на конкретное задание.
Если задача случайно запущена без символа » & «, то ее можно или завершить комбинацией клавиш Ctrl+C и потом запустить правильно, или «заморозить», нажав Ctrl+Z , а потом перевести в фоновый режим командой » bg » (сокращение от BackGround):
bobby:~% xcalc zsh: suspended xcalc bobby:~% bg %1 [1] + continued xcalc bobby:~% _
Бывает и обратное: случайно интерактивная программа (например, текстовый редактор) запущена в фоновом режиме. Интерактивные программы при этом автоматически «замораживаются» (потому, что они пытаются читать с терминала, который ей «не принадлежит»). Перевести их в «основной режим» можно командой » fg » (сокращение от ForeGround):
bobby:~% emacs -nw & [1] 2637 bobby:~% [1] + suspended (tty output) emacs -nw bobby:~% fg %1 [1] + continued emacs -nw
Если попробовать набрать » exit » для выхода из системы (или из окна терминала) при исполняющихся в фоновом режиме задачах, то zsh не позволит выйти:
bobby:~% xcalc & [1] 2691 bobby:~% exit zsh: you have running jobs. bobby:~% _
Повторная команда » exit » все же будет выполнена, но zsh постарается завершить фоновые задачи:
bobby:~% xcalc & [1] 2700 bobby:~% exit zsh: you have running jobs. bobby:~% exit zsh: warning: 1 jobs SIGHUPed
Чтобы zsh не считал своей обязанностью «убитие» фоновых задач при выходе, можно заставить его забыть про них:
bobby:~% xcalc & [1] 2701 bobby:~% jobs [1] + running xcalc bobby:~% disown %1 bobby:~% jobs bobby:~% _
Чтобы запустить фоновую задачу и заставить zsh сразу же забыть про нее, надо набрать всю команду (включая » & «) в круглых скобках:
bobby:~% (xcalc &) bobby:~% jobs bobby:~% _
Допустим, запустив задачу в фоновом режиме, пользователь выходит из системы, оставляя задачу работать дальше. Хорошо, если это была графическая программа — у нее почти наверняка будет хотя бы команда «Выход». А если нет, если это какая-либо счетная задача?
В этом случае придется воспользоваться средствами более низкого (системного) уровня — управлением процессами.
Здесь следует сразу понять разницу. Задача (job) — это одна или несколько программ (например, конвейер), запущенных из оболочки, которыми можно управлять при помощи команд оболочки jobs , bg , fg и kill . Процесс (process) — это любая программа, запущенная любым способом (из оболочки; другой программой — например, из графического меню; самой операционной системой при запуске и т.д.).
Для просмотра списка процессов служит команда » ps «. У нее есть довольно много ключей, которые к тому же различаются в BSD и SystemV. Поэтому здесь приведем лишь несколько наиболее часто встречающихся вариантов ее использования. В основном изложение относится к BSD-версии команды ps (в том числе и Linux), эквиваленты для SysV-версии (Solaris, IRIX) приведены отдельно.
Команда ps без параметров выводит список почти всех процессов, принадлежащих запустившему ее пользователю.
bobby:~% ps PID TTY STAT TIME COMMAND 2950 1 S 0:00 -zsh 2971 1 R 0:00 ps bobby:~% _
Из всей информации, что выдает ps , для нас пока интересны поля PID и COMMAND.
PID (Process IDentifier) — это число, уникальное для каждого процесса, которое используется, например, для того, чтобы приостановить или завершить его исполнение. COMMAND — название программы и ее параметры.
«Почти» — потому, что в список не включаются процессы «без терминала», т.е. те, которые запущены в фоновом режиме, а окно, из которого это было сделано, потом было закрыто. Чтобы эти процессы также отображались, надо указать ключ » -x «; в поле TTY у них стоит » ? «.
Ключ » -a » показывает процессы всех пользователей, а не только запустившего ps.
Ключ » -u » выдает более полную информацию о каждом процессе — потребление процессорного времени, памяти, время запуска.
Ключ » -f » выдает список процессов «со связями», позволяя понять, какой из процессов является чьим «родителем» и чьим «потомком».
Если у пользователя запущено много процессов (например, когда он находится в графической оболочке), то список обычно не помещается на экран. В этом случае надо отправить вывод команды ps команде less . Другой часто используемый прием — если интересует информация о какой-то конкретной команде, то вывод ps фильтруется через grep . Пример:
bobby:~% ps -x | grep xcalc 3103 ? S N 0:00 xcalc 3107 p9 S 0:00 grep xcalc bobby:~% _
Следует заметить, что в получившийся список может попасть и сам grep — в его командной строке тоже присутствует искомое слово, а поскольку ps и grep исполняются параллельно (а может и не попасть, в случае если команда ps отработает раньше, чем запустится grep ).
На это надо просто не обращать внимания — просто команда ps сейчас находится в процессе переделки со стандарта BSD на стандарт Unix98, и это предупреждение — следствие попытки обеспечить совместимость.
- » ps » без параметров выводит список процессов, запущенных в данной сессии (т.е. в том же окне, что и ps).
- » ps -u пользователь » выводит список всех процессов указанного пользователя.
- » ps -e » показывает все процессы (аналог » ps -a » в BSD)
- » ps -f » показывает более полную информацию (аналог » ps -u » в BSD)
Команде kill можно указывать не только номер задания, но и PID. Так, команда » kill 1206 » пошлет команду завершения процессу с номером 1206. Стоит напомнить, что при запуске задач оболочка кроме номера задания печатает также PID соответствующего процесса (или процессов, в случае конвейера):
bobby:~% xcalc & [1] 3206 bobby:~% kill 3206 bobby:~% [1] + terminated xcalc bobby:~% _
Вообще говоря, » kill » не завершает процесс, а посылает ему сигнал . Процесс же, получив сигнал, может завершиться, а может и предпринять какое-либо другое действие, например, проигнорировать сигнал.
Есть несколько десятков сигналов, каждый из которых имеет свой смысл. Каждый сигнал имеет как имя, так и номер, но, поскольку номера разные в разных Unix’ах, то лучше использовать имена. Чтобы указать kill , какой сигнал послать, надо указать его имя (или номер), предваренное дефисом:
bobby:~% xcalc & [1] 3388 bobby:~% kill -INT 3388 bobby:~% [1] + interrupt xcalc bobby:~% _
Вот список самых часто употребляемых сигналов:
Сигнал | Назначение |
---|---|
TERM | TERMinate — завершить работу. Используется командой kill по умолчанию |
INT | INTerrupt. Посылается при нажатии пользователем Ctrl+C |
STOP | «замерзнуть» |
CONT | CONTinue — «размерзнуть» |
HUP | HangUP — «повесить трубку». Посылается при выходе пользователя из системы программам, запущенным в этой же сессии |
KILL | «умереть» |
Сигналы TERM, INT, HUP и KILL обычно приводят к завершению работы программы. Разница между ними в том, в каких случаях они посылаются и в том, что одни сигналы программа перехватывает, а другие — нет.
Сигнал KILL программа перехватить не может, поэтому если она не реагирует больше ни на что, то остается использовать его. Номер KILL во всех Unix’ах — 9, поэтому его часто указывают по номеру, а не по имени — » kill -9 «. Сигнал KILL следует использовать только в крайних случаях, когда ничто другое не помогает. Дело в том, что перехватив, к примеру, сигнал TERM, программа может корректно завершить работу, при надобности сохранив данные в файлы и восстановив правильное состояние терминала, а KILL не дает ей такой возможности.
Вообще говоря, большая часть функций по управлению заданиями реализуется при помощи сигналов. Так, послав программе сигнал STOP, получим тот же эффект, что и при нажатии Ctrl+Z .
В большинстве современных Unix’ов есть возможность послать сигнал процессу, указав его не по номеру, а по имени программы. Для этого служит команда » killall » — она посылает сигнал всем процессам с указанным именем. Пример:
bobby:~% xcalc& [1] 3478 bobby:~% xcalc& [2] 3479 bobby:~% killall xcalc [1] - terminated xcalc [2] + terminated xcalc bobby:~% _
Не стоит ей злоупотреблять — эта команда мало того, что «убивает» все процессы с таким именем, она пытается «убить» даже процессы с таким именем у других пользователей (чего ей Unix, естественно, не позволяет сделать).
В большинстве современных клонов Unix есть программа, позволяющая оперативно отслеживать, какие процессы запущены в системе и какие из них потребляют больше всего процессорного времени. Эта программа называется » top «.
11:33pm up 1 day, 6:20, 12 users, load average: 0.00, 0.00, 0.09 81 processes: 78 sleeping, 3 running, 0 zombie, 0 stopped CPU states: 12.8% user, 2.5% system, 0.3% nice, 85.4% idle Mem: 63136K av, 59612K used, 3524K free, 39772K shrd, 1000K buff Swap: 128516K av, 12552K used, 115964K free 14852K cached PID USER PRI NI SIZE RSS SHARE STAT LIB %CPU %MEM TIME COMMAND 400 root 17 0 26444 19M 1600 R 0 6.9 32.1 137:51 X 1887 ivanov 10 0 4312 4240 3232 R 0 4.0 6.7 117:04 xdos 3505 ivanov 10 0 740 740 564 R 0 2.3 1.1 0:01 top 402 ivanov 1 0 1028 968 560 S 0 0.7 1.5 0:11 fvwm2 2148 ivanov 6 5 2548 2436 644 S N 0 0.3 3.8 0:14 xfte 415 ivanov 0 0 1024 1004 780 S 0 0.1 1.5 0:07 xrus 508 ivanov 1 0 18144 13M 3764 S 0 0.1 21.3 1:06 netscape 3135 root 1 0 1696 1696 1204 S 0 0.1 2.6 0:05 nxterm 3460 root 1 0 832 832 600 S 0 0.1 1.3 0:00 ssh 1 root 0 0 284 244 224 S 0 0.0 0.3 0:04 init 2 root 0 0 0 0 0 SW 0 0.0 0.0 0:00 kflushd 3 root -12 -12 0 0 0 SW< 0 0.0 0.0 0:00 kswapd 4 root 0 0 0 0 0 SW 0 0.0 0.0 0:00 md_thread 5 root 0 0 0 0 0 SW 0 0.0 0.0 0:00 md_thread 398 ivanov 0 0 520 468 412 S 0 0.0 0.7 0:00 startx 380 ivanov 0 0 740 644 524 S 0 0.0 1.0 0:00 zsh 362 root 0 0 228 196 180 S 0 0.0 0.3 0:00 gpm
top показывает процессы по убыванию «потребления» процессора. («top» — верхушка, вверху показываются те процессы, которые потребляют больше). К сожалению, как видно из приведенного примера, сам top также потребляет немало — на старых компьютерах типа 486 он иногда пожирал больше 10%.
Где брать информацию про shell
Поскольку команды jobs , bg и fg — это внутренние команды оболочки, то их описание следует искать в описании оболочки. Информация про перенаправление ввода/вывода имеется там же.
Для оболочек bash и tcsh лучше всего смотреть man-страницы. Для zsh — info-документацию:
соответственно.
Шеллы что это в программировании
Shell является не только интерпретатором команд, но и языком программирования на уровне команд. Это означает, что вместо того, чтобы использовать shell только как взаимосвязь между вами и компьютером, вы можете программировать с его помощью для автоматического повторения последовательности инструкций. Чтобы сделать это, нужно создать исполняемый файл, содержащий список этих команд. Эти файлы называются процедурами shell. Создав такую процедуру для определенной задачи, вы можете просто запросить shell прочитать и выполнить содержание процедуры.
Подобно другими языкам программирования shell обеспечивает такие возможности как переменные, управление структурами, подпрограммы, передача параметров. С помощью этих возможностей вы можете создавать собственный инструментарий.
Например, вы можете скомбинировать три команды системы UNIX (date, who, wc) в простой процедуре shell и назвать его users. Эта процедура отражает дату, время и количество пользователей, работающих в вашей системе. С помощью редактора vi создайте файл users:
vi users
Редактор выведет пустую страницу на вашем экране и будет ждать ввода текста. Введите три команды на одной строке:
date; who | wc -l
Затем запишите текст в файл и выйдите из файла, задав команду:
Сделайте файл users исполняемым:
chmod ug+x users
Теперь попытайтесь запустить этот файл. На экране появится информация, подобная:
$ users Sat Mar 11 16:40:32 EST 1989 4 $
Команда распечатывает дату и количество пользователей (4).
4.2.10. Программирование с помощью awk
awk предлагает вам управлять задачами обработки данных и восстановления информации. В разд. 7 приводится концепция языка и структура программы awk.
Типичная программа awk состоит из выражения «шаблон-действие». awk-программа находит во вводном файле строку, соответствующую шаблону и выполняет над ней указанное действие. Процесс продолжается до тех пор, пока весь вводной файл не будет прочитан.
Comments: info@citmgu.ru Designed by Andrey Novikov Copyright © CIT |