Тестирование многозначного статуса выхода (не только успеха или неудачи)

Я создал новый подтом «home» в новом каталоге /home на /dev/sda2. Скопировал данные old/home в new/home, а затем настроил fstab на:

# /dev/sdb1 LABEL=archroot
UUID=23cef669-f46c-4f5b-8476-ba548256e754   /           btrfs       rw,noatime,compress=lzo,ssd,subvolid=257,subvol=/@root,subvol=@root  0 0

# /dev/sdb1 LABEL=archroot   OLD/HOME on SSD  ID 258 gen 3060 top level 5 path @home
# UUID=23cef669-f46c-4f5b-8476-ba548256e754 /home       btrfs       rw,noatime,compress=lzo,ssd,subvolid=258,subvol=/@home,subvol=@home  0 0

# /dev/sdb1 LABEL=archroot
UUID=23cef669-f46c-4f5b-8476-ba548256e754   /.snapshots btrfs       rw,noatime,compress=lzo,ssd,subvolid=259,subvol=/@snapshots,subvol=@snapshots   0 0

# /dev/sda2 LABEL=archhome   NEW/HOME on HDD  ID 260 gen 30 parent 5 top level 5 path home
UUID=7ad83a78-4e19-45df-9c6e-1d931a9f999c       /home           btrfs           rw,noatime,compress=lzo,space_cache,subvolid=260,subvol=home 0 0

Работает как шарм. Я что-то забыл? Любые подсказки? Я надеюсь, что смогу делать снимки и из этого нового /дома.

0
15.07.2019, 14:11
2 ответа

Если file1и file2существуют и равны, ваш фрагмент кода, как показано, генерирует синтаксическую ошибку:unexpected end of file. Это происходит из-за незавершенного оператора if, когда оболочка достигает конца сценария до того, как встретит соответствующий оператор fi. Это вызвано наличием elif ifвместо elif. Если в остальной части вашего кода нет других ошибок, это должно решить проблемы, о которых вы сообщили.

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

if diff --strip-trailing-cr file1 file2 > /dev/null; then
  echo "no diff"
elif [ $? -eq 1 ]; then
  echo "there is diff"
else
  echo "something is wrong"
fi

Кстати, при написании шелл-скриптов очень полезно проверять их с помощью ShellCheck — инструмента анализа шелл-скриптов .

3
28.01.2020, 02:39

Ваш код с исправлением тривиальных опечаток выглядит так:

(1)      diff --strip-trailing-cr "$file1" "$file2" > /dev/null
(2)      if [ $? -eq 0 ]; then
(3)        echo "no diff"
(4)      elif [ $? -eq 1 ]; then
(5)        echo "there is diff"
(6)      else
(7)        echo "something is wrong"
(8)      fi

(Номера строк в приведенном выше приложении, конечно, только для иллюстрации, и не являются частью скрипта. )Это небольшая ошибка, на которую никто не указал. — независимо от статуса выхода diff, раздел echo "something is wrong"никогда не будет достигнут. Вы можете легко проверить это, заменив команду diffна (exit "$1")а затем передавать числа, например 0, 1, 2, 3и т. д., в качестве аргументов.

Проблема в том, что $?является изменчивой переменной. В строке 2 это, конечно, статус выхода из команды(diff)в строке 1. Но в строке 4 $?— это статус выхода из команды[ $? -eq 0 ](test )в строке 2. Если статус выхода из diffотличается от 0, то тест [ $? -eq 0 ]установит для $?значение 1, и, вы будете всегда получать there is diffсообщение.

Есть несколько способов справиться с этим. Один из них — сохранить статус выхода diffв стабильной переменной :

.
diff --strip-trailing-cr "$file1" "$file2" > /dev/null
diff_exit_status=$?
if [ "$diff_exit_status" -eq 0 ]; then
  echo "no diff"
elif [ "$diff_exit_status" -eq 1 ]; then
  echo "there is diff"
else
  echo "something is wrong"
fi

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

Во-вторых, использовать оператор case:

diff --strip-trailing-cr "$file1" "$file2" > /dev/null
case "$?" in
  (0)
      echo "no diff"
      ;;
  (1)
      echo "there is diff"
      ;;
  (*)
      echo "something is wrong"
esac
3
29.02.2020, 00:54

Теги

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