Управление заданиями

    Наверное всякий nix-оид знает что запуская команду с амперсандом на конце — она уходит в фон, продолжая работу.
    Таким образом запущенная команда превращается в job (задание).
    Более продвинутые знают что можно вывести список запущенных заданий командой jobs, и переключиться между ними командами fg (вывести фоновую задачу в оболочку)/ bg (отправить остановленное задание в фон). Остальными командами пользуются куда реже, а большинство начинающих линуксоидов про них читали мельком, но забыли, или вообще никогда не знали. А между прочим кроме: jobs, fg и bg есть disown, wait и даже kill.
    Не считая тех, что можно использовать внутри задания или для управления написанными выше командами: enable, builtin.
    Итак если вам интересно как делается:
    1. Приостановка job-в. Остановка (kill).
    2. Запуск ранее приостановленного job-а.
    3. Advanced нумерация заданий.
    4. Ожидание завершения фоновых задач.
    5. Команда disown.


    Запустим три задания:
    $ nice gzip < /dev/zero > /dev/null &
    [1] 15727
    $ bzip2 < /dev/zero > /dev/null &
    [2] 15728
    $ xz < /dev/zero > /dev/null &
    [3] 15730


    Три задания, с номерами 1, 2, 3. и их PID-ами.

    Остановка заданий



    Приостановка

    Приостанвим задание, например первое:
    это сделает команда kill, передавая сигнал SIGSTOP.
    kill -SIGSTOP %1

    В данном случае использовалась внутренняя команда bash-а: kill, а не внешняя программа /bin/kill.
    Да, /bin/kill тоже можно использовать для того чтобы передать сигнал SIGSTOP, но внешняя программа не умеет обращаться с номером задания, ей подавай PID.
    В линуксе еще достаточно удобно: 4-5 значный PID (2 байта), но в AIX-е pid-ы в основном 8значные PIDы, а могут иметь и 9 цифр, к тому же не последовательны, а разбросаны по своему 4байтному диапазону.

    Сигнал SIGSTOP — это один из трех сигналов которые приложение не может игнорировать (SIGSTOP, SIGCONT, SIGKILL который обычно 9). Да, конечно у каждого из них есть и числовой код (например kill -9 означает kill -SIGKILL), но не на всех платформах они совпадают. Узнать их соответствие можно или из документации (man signal/man 7 signal/man kill), или прямо (внутренней)командой kill -l.

    Завершение задания

    Аналогично:
    kill -SIGKILL %1 или PID процесса.

    Запуск приостановленного ранее

    bg %1 — отправка приостановленного задания выполняться в фон.
    fg %1 — переключение в остановленное (или запущенное задание)

    Еще вариант: переключиться в это задание и остановить его Ctrl+Z:
    $ fg %1
    nice gzip < /dev/zero > /dev/null
    ^Z
    [1]+  Stopped                 nice gzip < /dev/zero > /dev/null
    


    Advanced нумерация заданий


    Вот у меня продолжают сжимать нули три процесса:
    [1]  15727 Running                 nice gzip < /dev/zero > /dev/null &
    [2]- 15728 Running                 bzip2 < /dev/zero > /dev/null &
    [3]+ 15730 Running                 xz < /dev/zero > /dev/null &
    


    Первое поле в квадратных скобках — номер job-а. К нему можно обратиться такими командами как fg, bg, kill (внутренней), disown, wait.

    Второе поле: имеет - (минус) для 2го задания и + (плюс) для 3го — это номера заданий в нотации: «Последнее» и «Текущее».
    Текущее — это то «с которым мы работаем сейчас». Если у нас запущенно одно задание — то только оно будет иметь +. Если мы переключимся на другое задание командой fg — оно станет «текущим». Команды fg и bg без номера заданий будут работать с Текущим. К нему можно также обратиться через %+ или %%

    Последнее — это то, которое было перед «Текущим». Если мы завершим текущее (kill -9 %% ) — то Последнее станет Текущим. Этакий стек заданий. К нему можно обратиться через %-

    Также для команд fg, bg, kill, disown, wait к заданиям можно обратиться через имя запускаемой команды:
    запустим еще sleep
    kill -9 #x 

    Убъет только одно задание, который начинается на x (у меня пострадает архивация командой xz)

    kill -9 #?gzip

    убьет команду, которая содержит gzip. ( Такой процесс у меня тоже только один), а если маска такая, что в неё входит несколько заданий (например в предыдущей команда kill -9 #?zip, то такое не получится, т.к. и nice gzip и bzip2 попадают под такую маску, и нельзя точно определить к какому заданию относится команда. Хотя странно: для fg то еще можно понять что нужен один аргумент, а kill может принимать несколько аргументов, bg не может но мог бы, но в общем все команды не могут разобраться c неоднозначными масками)

    Подробнее смотрите таблицу из ABS Guide

    enable и builtin

    Тут то и следует рассказать о командах enable и builtin:
    Из ссылки выше:

    Конструкция builtin BUILTIN_COMMAND запускает внутреннюю команду «BUILTIN_COMMAND», на время запрещая использование функций и внешних системных команд с тем же именем.
    enable Либо запрещает, либо разрешает вызов внутренних команд. Например, enable -n kill запрещает использование внутренней команды kill, в результате, когда интерпретатор встретит команду kill, то он вызовет внешнюю команду kill, т.е. /bin/kill.


    Внутренние команды вызываются быстрее чем внешние, полноценные программы, хотя бы потому, что нет необходимости форкать дочерний процесс, переключаться между ними. Список внутренних команд можно посмотреть enable -a.

    Ожидание завершения фоновых задач


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

    cat url.list | while read url ; do wget -qc "$url" & done
    wait 
    mv ./* /media/flash/
    

    Запустит одновременно закачку по списку всех url, и только когда будет завершатся все закачки — перекинет их на флешку.

    Команда disown


    disown — Удаляет задание из таблицы активных заданий командной оболочки. Т.е. процесс продолжает работать в фоновом режиме, но уже не является заданием.
    Полезно процессам запущенных командой nohup — она перехватывает сигнал SIGHUP, а также забирает потоки вывода к себе в файл nohup.out.

    Также есть команды: suspend, times и logout, и times.
    Например times %N — выводит накопленное время в userspace и system для job-а и текущей оболочки. Suspend приостаналивает текущую оболочку, как это можно было бы сделать нажав ctrl+Z для другой команды, но при условии что текущая оболочка работает не в режиме login shell. Но даже не представляю как их можно применять.
    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 14

      +4
      я бы ctrl+Z акцентировал внимание, очень полезная штука
        +1
        Сколько раз я на эту полезную штуку нажимал по запарке… не счесть :)
        0
        Пошел проверять все эти трюки в csh на фряхе. Проверю — отчитаюсь. За статью спасибо.
          –3
          Вот странно — я знаю все эти команды, но никак не могу уловить их глубокого сакрального смысла. Кому и зачем они нужны? Что нужно делать на сервере, чтобы понадобилось плодить множество заданий? А на десктопе это вообще как-то бессмысленно…

          Мне кажется, это наследие тех времен, когда компьютеры были большими, работали в терминальном режиме и не имели графического интерфейса.

          Кто-нибудь применяет это сейчас на практике? Как?
            +1
            Я например часто использую когда надо в одной ssh-сессии запускать несколько скриптов. Или та же загрузка wget-ом.
            Хотя с wget-ом интереснее: если есть список URL, то качаем в 5 потоков:
            xargs -L1 -P4 wget -q < url.list 
              0
              * -P4 — в 4 потока.
              • UFO just landed and posted this here
                • UFO just landed and posted this here
                0
                ну, к примеру, я запустил на сервере ftp-клиент, но мне надо посмотреть какие-то имена файлов или еще что-нибудь вроде того… ctrl+z, погулял-посмотрел, fg. Это самый простой пример.
                –2
                Автор нашел новую для себя страничку в man? :)
                  0
                  спасибо большое, пользовался только ctrl+z и fg но часто бывала нужда в bg и &, а не знал что так возможно…
                    +4
                    > В линуксе еще достаточно удобно: 4-5 значный PID (2 байта)

                    Не вводите в заблуждение про 2 байта, максимум настраивается:

                    # cat /proc/sys/kernel/pid_max
                    32768

                      0
                      Ухты, не знал что настраивается обычным sysctl.
                      0
                      Спасибо за статью…

                      Only users with full accounts can post comments. Log in, please.