У меня очень базовые навыки работы с Linux, и сейчас я пытаюсь разобрать некоторые скрипты оболочки. Я вижу эту строку в одном из скриптов:
if [ -n "$(which voltdb 2> /dev/null)" ];
Я знаю, что /dev/null — это битовый контейнер, который выводит путь, который был бы выполнен, если бы я запустил voltdb в командной строке. Кроме того, вся строка, очевидно, является оператором if. Но меня смущает многое другое.
- Почему 2 сравнивается с /dev/null? Похоже, что это несовместимые типы.
- Что делает переключатель -n? Я привык использовать переключатели типа rm -r filename, но -n, похоже, не сочетается ни с одной командой
- Что делают скобки? Кажется, здесь они означают что-то другое, чем в этом выраженииКаково значение этого тестового выражения []?
В общем, что делает эта строка? Для меня в ней слишком много неизвестных — это как будто слышишь предложение на иностранном языке и пропускаешь так много слов, что не можешь уловить основную структуру.
решение1
В этом фрагменте кода происходит много всего. Работаем изнутри наружу:
which voltdb 2> /dev/null
- Команда, выполняемая здесь which
, . which
при вызове будет искать все записи в PATH
переменной среды, чтобы найти команду с именем "voltdb". Если она найдет исполняемый файл с именем "voltdb" в одном из каталогов, указанных в PATH
, она выведет полное имя voltdb
исполняемого файла.
Чтобы ответить на ваш #1, "2>" является примером перенаправления. Каждый процесс Unix/Linux/*BSD имеет 3 стандартных ввода и вывода, 0 - это stdin, 1 - это stdout, 2 - это stderr. Программы, предназначенные для запуска в командной строке, обычно выводят сообщения об ошибках на stderr. Таким образом, "2> /dev/null" не является числовым сравнением 2 с "/dev/null", он отправляет любой which
вывод об ошибках в /dev/null
, специальный файл, который просто съедает любой ввод и возвращает 0 байт вывода.
За пределами этого $(...)
конструкция означает «запустить прилагаемую команду и лексически заменить любой вывод прямо здесь, между '$(' и ')'». Это подстановка вывода, то, что делают программы оболочки.
За пределами подстановки вывода фрагмент делает if [ -n "something" ];
, где "something" — это то, что which
было бы напечатано. "if" — это конструкция потока управления оболочки, которая вызывает выполнение блока кода, когда конвейер команд после "if" завершается со статусом "success".
На самом деле это [
исполняемый файл, который просматривает аргументы командной строки вплоть до ]
. Флаг "-n" обычно означает "истина для ненулевой длины строки следующего аргумента". Это ответ на ваши вопросы № 2 и № 3. Конструкция [ ... ]
дает ответы "истина" (выход с кодом успеха) или "ложь" (выход с кодом ошибки) на некоторые логические условия, в данном случае "ненулевая длина строки".
В конечном итоге этот фрагмент выполнит условие «истина» потока управления if-then-fi или if-then-else-fi, когда voltdb
в PATH этой оболочки есть каталог с исполняемым файлом.
решение2
Этот код делает следующее:
if [ -n "...." ];
Оператор if истинен, если результат выполнения кода в двойных кавычках пуст.
Код в двойных кавычках:
$(which voltdb 2> /dev/null)
Запускает which voltdb
команду и перенаправляет любой вывод этой команды, который появляется на STDERR (стандартная ошибка), в /dev/null
. По сути, он нам не интересен, поэтому мы его игнорируем.
Результаты which voltdb
вернут путь к любому исполняемому файлу в вашем PATH, который соответствует строке voltdb.
Пример
$ which time
/usr/bin/time
$ which time 2> /dev/null
/usr/bin/time
Что насчет 2>
?
2>
это сокращенная запись для перенаправления вывода одного изпотокикоторый автоматически настраивается для программы при ее запуске. Потоки следующие:
- 0 - стандартный вход (STDIN)
- 1 - стандартный вывод (STDOUT)
- 2 - стандартная ошибка (STDERR)
Итак, если вы хотите взять вывод STDERR и избавиться от него:
$ which time 2> /dev/null
Если вы хотите взять вывод из STDOUT и перенаправить его в STDERR: