Linux выполнить команду после завершения предыдущей

Обновлено: 04.07.2024

при выполнении команд из сценария bash bash всегда ждет завершения предыдущей команды или просто запускает команду, а затем переходит к следующей?

ie: если вы запустите следующие две команды из сценария bash, возможно ли, что что-то не удастся?

да, если вы ничего не делаете, то команды в сценарии bash сериализуются. Вы можете сказать bash, чтобы запустить кучу команд параллельно, а затем дождаться их завершения, но делать что-то вроде этого:

амперсанды в конце каждой из первых трех строк говорят Башу выполнить команду в фоновом режиме. Четвертая команда:--1-->, говорит bash подождать, пока все дочерние процессы не выйдут.

обратите внимание, что если вы делаете вещи таким образом, вы не сможете получить статус выхода дочерних команд (и set -e не будет работать), поэтому вы не сможете сказать, удалось ли им или не удалось обычным способом.

на руководство bash больше информации (поиск wait , примерно две трети пути вниз).

добавить '&' в конце команды, чтобы запустить его параллельно. Однако это странно, потому что в вашем случае вторая команда зависит от конечного результата первой. Используйте последовательные команды или скопируйте в b и c из a следующим образом:

Если вы явно не скажете bash запустить процесс в фоновом режиме, он будет ждать, пока процесс не завершится. Поэтому, если вы напишете это:

bash будет продолжаться, не дожидаясь выхода foo. Но если вы явно не ставите процесс в фоновом режиме, bash будет ждать его выхода.

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

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

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

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

Так, например, если я запустил:

и нажмите enter . как я могу запустить другую команду после ее завершения?

Вы можете отделить несколько команд командой ; , поэтому они выполняются последовательно, например:

Если вы хотите выполнить следующую программу, только если скрипт закончил с кодом возврата 0 (что обычно означает, что он выполнен правильно), то:

Если вы хотите противоположное (т. е. продолжать только в случае сбоя текущей команды), чем:

Вы можете запустить свой сценарий в фоновом режиме (но будьте осторожны, вывод скриптов ( stdout и stderr ) будет продолжать идти на ваш терминал, если вы не перенаправите его где-нибудь), а затем wait для этого:

Если у вас есть скрипт запуска alredy, вы можете приостановить его с помощью Ctrl-Z , а затем выполнить что-то вроде:

Где fg переносит приостановленный процесс на передний план ( bg заставит его работать в backgroung, в значительной степени, как начатый с & )

Вы также можете использовать управление заданиями bash. Если вы запустили

, затем нажмите ctrl + z, чтобы приостановить его:

, чтобы перезапустить задание в фоновом режиме (как если бы он был запущен с помощью really_long_script.sh & ). Затем вы можете подождать, пока это фоновое задание с помощью

где N - это идентификатор задания (возможно, 1, если вы не запускали никаких других фоновых заданий), который также отображается как [1] выше.

Если процесс не запускается на текущем tty, тогда другой вариант будет:

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

Я предполагаю, что есть более элегантные способы, но, похоже, это работает.

Редактирование, чтобы добавить, что если вы хотите запустить оповещение после завершения команды, вы можете создать эти псевдонимы в .bashrc, затем запустите alert пока он запущен:

Некоторое время назад я написал сценарий, чтобы дождаться окончания другого процесса. NOISE_CMD может быть что-то вроде notify-send . , данный что DISPLAY установлен правильно.

Без какого-либо сегмента, немедленно сделайте некоторый шум. Это поведение позволяет что-то подобное для удобства (скажем, вы называете скрипт ниже alarm.sh ):

Бывшая версия сценария выше может быть интересной, если вы хотите избежать зависимости от pgrep и принять идентификаторы процесса поиска сами:

Немного не по теме, но полезно в аналогичных ситуациях: Возможно, вас заинтересует reptyr , инструмент, который «крадет» процесс из некоторой (родительской) оболочки и запускает ее из текущей оболочки. Я пробовал аналогичные реализации и reptyr является самым красивым и надежным для моих целей.

Я пытаюсь найти простой способ повторного выполнения команды всякий раз, когда она завершается, по любой причине (ошибка или нет).

Как лучше всего подойти к этому?

РЕДАКТИРОВАТЬ: Я не был достаточно ясным, прежде чем. Мне нужно следующее выполнение, чтобы дождаться окончания предыдущего.

Команда watch будет повторять команду всегда с указанным интервалом:

Установка -n в ноль фактически устанавливает интервал в ничто (я думаю, что это действительно .1 секунды).

watch также имеют дополнительные преимущества выравнивания выходных данных, так что визуальные изменения могут быть легко видны, и имеют переключатель, чтобы выделить изменения с последнего запуска.

Это создает бесконечный цикл, выполняющий command снова и снова.

Простое решение будет:

; разделяет команды, позволяя использовать несколько команд в одной строке (Bash: Lists)

Вы можете планировать заранее во время выполнения команды (при условии, что она не является интерактивной) и ввести !! который выполнит предыдущую команду снова. Это работает, например, во время ping -c 5 .

Вы также можете определить функцию в bash :

Чтобы сохранить его, сохраните его в

Затем вы можете запустить свою команду следующим образом:

Если это определенная команда, которую вы хотите выполнить многократно (а не, например, какая-либо команда), вы можете заменить "$@" в этом фрагменте на вашу фактическую команду и назвать функцию, например, repeat_ping .

Чтобы сделать его бесконечным циклом, вы можете делать то, что предлагает @Dennis. Я рекомендую вам добавить период ожидания, если вы собираетесь использовать это в интерактивной оболочке, например:

В противном случае довольно неудобно прерывать этот бесконечный цикл с помощью Ctrl-Z .

Дайте while цикла логическое условие , например следующим образом :

Это будет выполняться снова и снова, пока bash не получит сигнал о прекращении процесса. Обычно в виде ctrl+c .

Вы также можете использовать команду watch для многократного запуска скрипта. Например, простые часы в вашем bash-терминале с использованием watch могут выглядеть так:

Опция -t указывает watch не отображать название процесса, который он запускает. Это дает чистый вывод только повторяющейся команды. Опция -n1 часы повторяться каждые n секунд. В этом случае -n1 будет интервалом в 1 секунду. Затем команда date +%T показывает время на момент завершения команды. Выполнение этой команды даст вам активные часы в вашем терминале.

Это, по существу такой же , как логическое значение во while цикла только с помощью рекурсивных вызовов функций.

(edit) Для того, чтобы помнить о ресурсах вашей машины, я добавил && wait чтобы при каждом запуске процесса циклы "ожидали", пока этот процесс не завершится со статусом выхода 0 до следующей итерации. Это полезно в интерактивном сценарии оболочки.

Видели про-юзеров Linux, которые эффективно работают в терминале? Хотите так же? Не вопрос: в этой статье мы собрали некоторые из полезных команд, которые помогут вам сэкономить время и повысить продуктивность.

Использование табов для автодополнения

Когда вы начинаете что-то вводить в терминале, вы можете нажать Tab и вам будут предложены возможные варианты продолжения, которые начинаются с введённой вами строки.

Например, если вы хотите скопировать файл с именем file1.txt , вы можете ввести только cp f , нажать Tab и увидеть возможные варианты.

Также Tab можно использовать для автодополнения команд.

Возвращение в последнюю рабочую директорию

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

Она вернёт вас в последнюю рабочую директорию и вам не придётся вручную вводить длинный путь.

Примечание Последняя рабочая директория хранится в переменной окружения OLDPWD ; вы можете использовать эту переменную для своих целей (попробуйте echo $OLDPWD ) или даже подложить команде cd - другой путь ( OLDPWD=/usr/bin cd - ).

Возвращение в домашнюю директорию

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

А вообще, можно ограничиться командой cd и получить тот же результат. В большинстве современных дистрибутивов Linux эта команда должна сработать.

Вывести содержимое каталога

Вы, наверное, догадываетесь, какая команда нужна для отображения содержимого каталога. Всем известно, что для этого можно использовать ls -l .

Однако не все знают, что можно обойтись командой ll .

Белкасофт , Удалённо , По итогам собеседования

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

Примечание На самом деле, ll является не отдельной командой, а псевдонимом для ls -l .

Запуск нескольких команд за раз

Допустим, вам нужно запустить несколько команд одну за другой. Что вы будете делать? Подождёте завершения первой команды, а затем запустите следующую?

Вместо этого вы можете использовать разделитель ; . Таким образом можно запустить несколько команд на одной строке. Вам не нужно ждать, пока какая-то из команд завершит свою работу, чтобы запустить следующую.

command_1; command_2; command_3

Примечание При запуске команд таким образом, они выполняются не параллельно, а последовательно. Если вам нужен именно первый вариант, то используйте конструкцию (command_1 &); (command_2 &) .

Запуск нескольких команд за раз при условии, что предыдущая команда была выполнена успешно

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

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

В этом случае вы можете использовать разделитель && , который запускает следующую команду только при условии, что предыдущая успешно завершилась.

Как пример использования && можно привести команду sudo apt update && sudo apt upgrade для обновления системы через терминал на системах, основанных на Debian.

Время убивать

Есть несколько способов «убить» программу. Команда killall сделает это по имени, а kill требуется номер процесса. Например, killall chrome убьёт все процессы chrome. Также можно послать любому процессу сигнал прерывания (как Ctrl+C) с помощью kill -INT <номер процесса> .

Пора остановиться

Чтобы поставить работающую команду на паузу нажмите комбинацию Ctrl+Z, а чтобы продолжить — % .

Простой поиск и использование предыдущих команд

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

Здесь поможет обратный поиск. С его помощью можно по заданному условию найти команду в истории.

Просто нажмите комбинацию Ctrl+R и введите часть команды. Затем вам будут показаны команды из истории, которые удовлетворяют заданному условию.

По умолчанию показывается только один результат. Чтобы увидеть больше результатов, нужно повторно нажать Ctrl+R. Чтобы выйти из поиска, нажмите Ctrl+C.

Учтите, что в некоторых оболочках Bash можно использовать Page Up и Page Down с условием поиска для автодополнения команды.

Выводим консоль из зависания после Ctrl+S

Многие привыкли использовать комбинацию Ctrl+S для сохранения. Однако после её использования в терминале, он часто зависает. Чтобы вернуть его в нормальное состояние, нажмите комбинацию Ctrl+Q.

Переход к началу или концу строки

Допустим, вы вводите длинную команду и вдруг понимаете, что вам нужно что-то изменить в её начале. Чтобы попасть в начало или конец строки вы можете несколько раз нажать клавишу стрелки влево/вправо или Home/End. А можете нажать Ctrl+A или Ctrl+E.

Чтение лог-файла в реальном времени

В ситуациях, когда вам нужно анализировать логи при запущенном приложении, можно использовать команду tail с флагом -f .

tail -f <путь к лог-файлу>

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

tail -f <путь к лог-файлу> | grep <регулярное выражение>

Кроме того, вы можете использовать флаг -F , чтобы tail продолжал работу даже в случае удаления лог-файла. Таким образом, когда лог-файл снова будет создан, tail продолжит логирование.

Если вы хотите просматривать системный лог в реальном времени, воспользуйтесь аналогичной опцией -f команды journalctl :

Чтение сжатых логов без извлечения

К счастью, в таких ситуациях всегда спасут z-команды. Они являются альтернативами обычных команд, которые используются для работы с логами вроде less , cat , grep .

Поэтому вы можете воспользоваться zless , zcat , zgrep и т.д., даже не извлекая логи.

Использование less для чтения файлов

Команда cat не всегда лучший выбор для отображения содержимого файла, особенно если он большой — cat выведет сразу весь файл.

Вы можете использовать Vi, Vim или другой терминальный текстовый редактор, но если вам просто нужно прочитать файл, то команда less подойдёт гораздо лучше.

less <путь к файлу>

В less можно искать нужную подстроку, листать по страницам, отображать номера строк и не только. А ещё less может читать не только текстовые документы, но ещё и архивы и другие типы файлов.

Использование аргумента предыдущей команды с помощью !$

Использование аргумента предыдущей команды может пригодиться во многих ситуациях. Например, вы создали директорию и вам нужно сразу в неё перейти.

Ещё лучше использовать alt+. . Множественное нажатие точки позволяет выбрать аргумент одной из нескольких предыдущих команд.

Использование предыдущей команды в текущей с помощью !!

С помощью !! можно вызвать даже всю предыдущую команду. Это особенно полезно в тех случаях, когда оказывается, что для запуска команды нужны рут-привилегии.

Быстрое sudo !! позволяет сэкономить немного времени.

Использование alias для исправления опечаток

Вероятно, вы уже знаете, зачем нужна команда alias . Её можно приспособить для исправления опечаток.

Представим, что вместо grep вы часто пишете gerp . Если вы установите псевдоним следующим образом, то вам не придётся больше перепечатывать команду:

К слову, для исправления опечаток не обязательно использовать псевдонимы — утилита The Fuck сама исправит предыдущую команду.

Перезагружаемся

Чтобы выключить компьютер из терминала, введите poweroff , а для перезагрузки — reboot .

Вставка скопированного текста в терминал

Здесь не всё однозначно, так как между дистрибутивами Linux и терминалами есть определённая разница. Но в общем случае вставить текст можно одним из следующих способов:

  • Скопируйте текст и кликните правую кнопку мыши для вставки (работает в Putty и других Windows-клиентах SSH);
  • Скопируйте текст и нажмите среднюю кнопку мыши (колёсико) для вставки;
  • Ctrl+Shift+C для копирования и Ctrl+Shift+V для вставки;
  • В некоторых эмуляторах терминала работает привычная комбинация Ctrl+V.

Завершить работающий процесс/команду

Возможно, это слишком очевидно. Если у вас запущена команда, работу которой вы хотите завершить, просто нажмите Ctrl+C и команде будет отправлен сигнал прерывания (SIGINT). А если вы хотите быстро покинуть терминал, нажмите комбинацию Ctrl+D, которая для баша и других интерактивных программ означает окончание ввода.

Команда для скриптов или команд, которым нужен интерактивный ответ

Команда yes может пригодиться, если какой-то скрипт/команда требует взаимодействия с пользователем, которое заключается только в нажатии Y каждый раз.

yes | <команда или скрипт>

Очистить файл, не удаляя его

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

Узнать, есть ли файл с определённым текстом

В терминале Linux можно искать разными способами. Если вам нужно узнать, есть ли файл(ы) с определённым текстом, можете воспользоваться этой командой:

grep -Pri <текст_для_поиска> <путь_к_директории>

Получаем справку для каждой команды

Почти все команды/инструменты командной строки содержат справку с указаниями по работе. Чтобы получить справку, воспользуйтесь этой командой:

Кроме того, порой можно получить более подробную справку с помощью команды man <команда> .

Получаем историю команд

Если вы хотите взглянуть на все команды, которые вы когда-либо запускали, введите history . Если вам нужен не полный список, а только несколько последних, воспользуйтесь командой fc -l .

Быстро запускаем команды из истории

При получении команд одним из вышеуказанных способов рядом с каждой командой находится её номер в истории. Чтобы быстро запустить команду из этого списка просто введите !<номер команды> .

Выполняем команду в обход истории

Если вы хотите выполнить команду так, чтобы она не сохранилась в истории, просто введите пробел перед командой.

Пишем длинные команды с удобством

Если зажать Ctrl, а затем нажать по очереди X и E, то откроется текстовый редактор, в котором можно будет спокойно записать длинную команду, а после выхода из него — выполнить её.

Восстанавливаем терминал

Если вы вывели в терминал сырые бинарные данные или ещё что-то, что выводить не стоило, то убрать увиденную абракадабру позволит команда reset .

Информация о файловых системах

Чтобы получить информацию о текущих смонтированных файловых системах с удобным оформлением по столбцам, введите команду mount | column -t .

Также вы можете воспользоваться командой findmnt , которая отображает информацию в виде красивого дерева и сама форматирует столбцы, а также может найти нужную файловую систему:

Деревья процессов

Есть инструмент pstree , который умеет рисовать красивые деревья процессов. Например:

Экран блокировки

Чтобы заблокировать экран, используйте команду $ loginctl lock-session .

Для разблокировки экрана введите команду $ loginctl unlock-session . Конечно, вряд ли вы сможете использовать терминал при заблокированном экране, однако вы можете пойти обходными путями. Например, можно создать задачу для разблокировки через какое-то время.

Супершелл

Чтобы запустить шелл от имени суперпользователя, можно воспользоваться командой sudo -s . Во многих источниках можно встретить вариант sudo su , который тоже работает, но медленнее, так как запускает лишний процесс.

Быстро открываем файлы в программе по умолчанию

Команда xdg-open позволяет открыть любой файл в соответствующей программе. Например, xdg-open file.txt откроет файл в текстовом редакторе по умолчанию.

Статус системных сервисов

Чтобы посмотреть статус системных сервисов, введите команду systemctl status или systemctl status <имя сервиса> , если вас интересует конкретный сервис.

Быстро ищем файлы

Если вам нужно найти файл, но вы не знаете, где конкретно он находится, можно воспользоваться командой find . Например:

Используем вывод одной команды в качестве аргумента другой

Чтобы использовать вывод одной команды в качестве аргумента другой, используйте конструкцию команда-2 $(команда-1) . Например:

Календарь

Команда cal может нарисовать календарь на текущий месяц (и даже выделить текущее число) или на другой промежуток:

Планировщик задач

Чтобы выполнить какую-то команду в нужное вам время, воспользуйтесь at :

echo команда-для-выполнения | at время_выполнения

Учтите, что эта команда может отсутствовать на вашей системе, и вам придётся установить её самостоятельно.

Получаем свой внешний IP

Чтобы получить свой внешний IP-адрес введите curl ifconfig.me или curl ipinfo.io/ip . Возможно, сначала вам придётся установить curl .

Прогноз погоды

Введите команду curl wttr.in/<нужный город> и получите красивую таблицу с прогнозом погоды:

Получаем таблицу ASCII

Чтобы получить быстрый доступ к таблице ASCII просто введите man ascii .

Простой калькулятор

Небольшие выражения можно вычислять прямо в терминале. Это можно сделать либо с помощью конструкции echo <выражение> | bc , либо echo $((<выражение>)) . Например:

Выполняем команду в другой директории и возвращаемся обратно

Если вы хотите выполнить команду в другой директории, но при это не хотите покидать текущую, то просто оберните команду скобками. Например, (cd /tmp && ls) . Здесь скобки запускают подшелл (subshell), внутри которого мы и выполняем cd .

Узнаём, какие библиотеки нужны команде/библиотеке

Чтобы узнать, какие динамические библиотеки нужны программе или библиотеке и как они будут разрешены при запуске, используйте команду ldd :

Узнаём, что лежит внутри файла

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

Многократный запуск команды

Чтобы запускать команду каждые несколько секунд (по умолчанию две) и смотреть на её вывод, воспользуйтесь командой watch <команда> .

Время на запуск команды

Чтобы узнать, сколько времени уходит на запуск команды, используйте time <команда> .

Системные вызовы команды

Чтобы узнать, какие системные вызовы совершает программа, введите strace <команда> .

Запоминаем набираемую команду

Если вы набираете какую-то команду и вам по какой-то причине нужно прерваться и, например, ввести другую команду, вы можете «запомнить» то, что вы ввели комбинацией Ctrl+U, а затем вставить комбинацией Ctrl+Y.

Выкачиваем сайты

Чтобы выкачать сайт используйте команду wget --random-wait -r -p -e robots=off -U mozilla <адрес сайта> .

Проводим туннели

С помощью команды ssh -N -L 2001:localhost:80 somemachine можно создать туннель от 80 порта на удалённой машине до 2001 на локальной.

Читайте также: