Выгода “команда, не найденная” из сценария оболочки

Нам установили mikrotik маршрутизатор на старой буровой установке. Вентилятор прекратил вращать и заставлять процессор нагреваться. Маршрутизатор затем запускается к Панике Ядра время от времени. После изменения вентилятора процессора все подходило.

Начиная с Вашего разгоняют Вашу машину, это может быть возможная причина.

5
10.12.2013, 19:09
3 ответа

Когда команда не найдена, статус выхода равняется 127. Вы могли использовать это, чтобы решить, что команда не была найдена:

until
  printf "Enter a command: "
  read command
  "$command"
  [ "$?" -ne 127 ]
do
  echo Try again
done

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

bash и zsh имейте специальное предложение command_not_found_handler функция (существует опечатка в bashпоскольку это называют command_not_found_handle там), который при определении выполняется, когда команда не найдена. Но это выполняется в контексте подоболочки, и это может также быть выполнено после команд, не найденных при выполнении функции.

Вы могли испытать желание проверить на существование команды заранее с помощью type или command -v, но остерегайтесь этого:

"$commands"

анализируется как, простые команды и псевдонимы не расширены, в то время как type или command возвратил бы true для псевдонимов и ключевых слов оболочки также.

Например, с command=for, type -- "$command" возвратил бы true, но "$command" (по всей вероятности) возвратил бы команду, не найденную ошибкой.

which может перестать работать по большому количеству других причин.

Идеально, Вы хотели бы что-то, что возвращает true, если команда существует или как функция, встроенная оболочка или как внешняя команда.

hash соответствовал бы тем критериям, по крайней мере, для ash и bash (нет yash ни ksh ни zsh). Так, это работало бы в bash или ash:

while
  printf "Enter a command: "
  read command
do
  if hash -- "$command" 2> /dev/null; then
    "$command"
    break
  fi
  echo Try again
done

Одна проблема с этим - это hash возвращает true также для каталога (для пути к каталогу включая a /). В то время как, при попытке выполнить его, в то время как это не возвратит команду, не найденную ошибкой, это возвратит a Is a directory или Permission Denied ошибка. Если Вы хотите покрыть для него, Вы могли бы сделать:

while
  printf "Enter a command: "
  read command
do
  if hash -- "$command" 2> /dev/null &&
     { [ "${command#*/}" != "$command" ] || [ ! -d "$command" ];}
  then
    "$command"
    break
  fi
  echo Try again
done
8
27.01.2020, 20:33
  • trap только для сигналов, которые определяются в signal(7). Не нахождение команды является просто отказом в exec семейство функций, которые возвратятся -1, не отправляют сигнал.
  • Лучший способ поймать несуществующие команды состоял бы в том, чтобы сделать что-то вроде этого.

    if ! type "$command" >/dev/null 2>&1; then
        echo "Try again, wrong command" 1>&2 # should output to stderr, not stdout
    else
        "$command"
    fi
    
4
27.01.2020, 20:33
  • 1
    я также поощрил бы Вас использовать type <cmd> и/или command -v <cmd> команды вместо which. unix.stackexchange.com/questions/85249 / … –  slm♦ 10.12.2013, 22:32
  • 2
    Некоторые оболочки как ksh, zsh и удар могут захватить на специальном предложении, ДОПУСКАЮТ ОШИБКУ несигнал. Не заключение в кавычки Ваших переменных не имеет смысла здесь. Обратите внимание, что все команды оболочки выполняются исполнительными функциями. –  Stéphane Chazelas 10.12.2013, 23:19
  • 3
    Отметьте это с bash, это не сказало бы это -aaaa например, неправильная команда. type -- "$command" в POSIX оболочки были бы правильным синтаксисом, но остерегались бы этого ash, даже последними версиями не является POSIX (хорошо Unix с тех пор type является дополнительным в POSIX) в том отношении. Можно хотеть использовать command -v instead (или hash, см. мой ответ). удаление –  Stéphane Chazelas 11.12.2013, 17:59

Вот еще один способ, который использует код Стефана Чазеласа, но с типом , и преодолевает ограничения типа ...

function isCommand () {
  #
  local _arg=" $(type -t "$1") "
  local _executables=' file alias keyword function builtin '
  #
  [[ "${_executables#*$_arg}" != "$_executables" ]]  && return 0
  ### if $_arg is NOT in $_executables, the two strings will be identical
  #
  return 1
}

while
  printf "Enter a command: "
  read command
do
  isCommand "$command"  && { "$command"; break; }
  #
  echo Try again
done

Примечания

  • В isCommand () ...
    • ... переменные дополняются, чтобы избежать частичного Спички.
    • ... type возвращает «файл» для любого файла с установленным битом выполнения. Так мы обнаруживаем внешние команды.
    • ... этот тест на включение в строку - один из самых неинтуитивных, о которых я знаю. Но он быстрый и не использует внешних команд, поэтому я использую его и оборачиваю вокруг него более интуитивно понятную функцию. Есть несколько других способов сделать это.
  • isCommand "$ command" && {"$ command"; перерыв; }
    Здесь используется список команд для логики выполнения «если-то». (см. справочную страницу bash в Shell Grammer, Lists )
    • Преимущества
      • ... более быстрое выполнение, чем обычное if [[... ]] конструкция
      • ... избегает сложной (и подверженной ошибкам) ​​логики нескольких тестов
      • ... аналогично ООП try / catch обработка исключений
    • Предостережение
      • ...В части «затем» после && или || несколько команд должны быть заключены в фигурные скобки, а последняя команда и ее аргументы должны заканчиваться точкой с запятой ; как в {cmd1 args; cmd2 args; } .
2
27.01.2020, 20:33

Теги

Похожие вопросы