Как установить RabbitVCS на CentOS 7 и nautlius 3?

Это неправильный способ написания:

#!/bin/sh -

set -e # Exit if any command fails

# If multiple args given run this script once for each arg
if [ "$#" -gt 1 ]; then
  for arg do
    "$0" "$arg"
  done
  exit
fi

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

test somestring

Краткая форма

test -n somestring

Возвращает true, если somestring не является пустой строкой. (test '' возвращает false, test anythingelse возвращает true (но остерегайтесь test -t в некоторых оболочках, который вместо этого проверяет, является ли stdout терминалом)).

Однако автор забыл кавычки вокруг переменной (на самом деле, на всех переменных). Это означает, что содержимое $2 подчиняется оператору split+glob. Поэтому если $2 содержит символы $IFS (пробел, табуляция и новая строка по умолчанию) или glob-символы (*, ?, [...]), это не будет работать должным образом.

И если $2 пуст (например, когда передано менее 2 аргументов или второй аргумент пуст), test $2 становится test, а не test ''. test вообще не получает никакого аргумента (пустого или иного).

К счастью, в этом случае test без аргументов возвращает false. Это немного лучше, чем test -n $2, который вместо этого вернул бы true (так как он стал бы test -n, таким же, как test -n -n), так что этот код, похоже, работает в некоторых случаях.

Подведем итоги:

  • для проверки передачи 2 и более аргументов:

    [ "$#" -gt 1 ]
    

    или

    [ "$#" -ge 2 ]
    
  • чтобы проверить, является ли переменная непустой:

    [ -n "$var" ]
    [ "$var" != '' ]
    [ "$var" ]
    

    все они надежны в POSIX-реализациях [, но если вам приходится иметь дело с очень старыми системами, возможно, придется использовать

    [ '' != "$var" ]
    

    вместо этого для реализаций [, которые подавляются значениями $var, например =, -t, ()...

  • для проверки, определена ли переменная (это можно использовать для проверки, передается ли скрипту второй аргумент, но использование $# намного проще для чтения и более идиоматично):

    [ "${var+defined}" = defined]
    

(или эквивалент с помощью формы test. Использование псевдонима [ для команды test является более распространенным).


Теперь о разнице между cmd1 && cmd2 и if cmd1; then cmd2; fi.

Оба запускают cmd2 только в случае успешного выполнения cmd1. Разница в том, что в случае && статус выхода из общего списка команд будет принадлежать последней команде, которая была выполнена (поэтому код failure, если cmd1 не возвращает true (хотя это не мешает set -e здесь)), а в случае if, это будет значение cmd2 или 0 (успех), если cmd2 не выполняется.

Поэтому в случаях, когда cmd1 используется в качестве условия (когда его отказ не должен рассматриваться как проблема), обычно лучше использовать if, особенно если это последнее, что вы делаете в скрипте, так как это определит статус выхода вашего скрипта. Это также делает код более разборчивым.

Форма cmd1 && cmd2 чаще используется как условия, как в:

if cmd1 && cmd2; then...
while cmd1 && cmd2; do...

То есть в контекстах, где нам важен статус выхода обеих команд.

3
18.03.2019, 05:44
1 ответ

Добавляю ответ здесь, так как я не могу комментировать Хиен Ли без дополнительных очков репутации. Я следовал руководству Хиен Ли, но мне все равно не повезло. Изучив системные сообщения, я обнаружил, что в журнале регистрируется трассировка стека python с зависимостью от gtkspell версии 3. После удаления gtkspell и обновления до библиотеки gtkspell3 это сработало

.
3
27.01.2020, 21:19

Теги

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