Комментарии 52
Запускаешь без -eux готовься к неприятностям
Вот что происходит, когда привык к С, а тебя заставляют писать на bash.
А вы, как я понимаю, полубог, пишущий без ошибок с первого раза?
В случае с bash тут безграмотность на лицо и не знание техники безопасности, обработки исключений, и правильного написания кода.
Простой пример, вы взяли бензопилу спилить дерево, не зная техники безопасности и правил работы с бензопилой приступили к работе, в итоге бензопила отскочила и отрезала вам ногу, или дерево упало вам на голову. Кто виноват Бензопила!??? Дерево!??? Вы сами? Значит ли это, что бензопила плохая и не безопасная? Подходит ли бензопила выкручивать шурупы? А можете ли вы спилить дерево отверткой?
Совершали ли вы опасные ошибки при написании shell-скриптов?
Конечно, не совершает ошибок только тот кто ничего не делает. И сервера удаленные убивал и систему на рабочем компе. Правда было это лет 20 назад. Наверное самые распространенные грабли на которые наступал, это были правила файервола на удаленном сервере.
Напомнило историю, как установщик драйверов nvidia по ошибке удалял папку /usr.
А по-моему, самым безрассудным было даже не игнорирование возможности проверки линтером, а игнорирование проверок вообще - лично я банально поостерёгся бы использовать подобный скрипт, не проверив его на имитации боевого окружения (ну и линтером бы, конечно, не побрезговал)
P.S. не знаю, насколько прославлен rm -rf среди программистов, а среди сисадминов - точно
Странный кейс описан в статье. Корневая причина заключается в том, что исполнитель просто не знает инструмент, которым решил воспользоваться. Ни одному человеку, который хоть немного писал на шелле, просто в голову не придёт так отмечать комментарии.
Линтер - это, конечно, симптоматичное решение. Но системно этот вопрос решается по другому. Выше правильно говорили про тестирование, но повторюсь - совершенно не ясно, почему не знающий шелла программист (и не важно, пишет он на Си или ПХП) вообще решал эту задачу.
Да даже если и писать коменты, то не понятно зачем на каждую строку.
Баш скрипты в целом плохо читаются, поэтому для профанов польза явно есть.
Другой вопрос конечно, почему новичок в баше лазает своими ручонками по серверу с БД-шкой…
Кстати, перевел гугл транслейтом:
Временный каталог для файлов резервных копий
Официальный каталог файлов резервных копий
Файл резервной копии будет сохранен во время резервного копирования.
Оператор базы данных
Пароль оператора базы данных
Сохраните последнюю резервную копию 14-летней давности
Формат имен файлов резервных копий
Создать папку
Очистите временный каталог
Создайте эту резервную папку
Выполнить команду резервного копирования
Упакуйте файл резервной копии в официальный каталог
Удалите старый Beizhou 14 дней назад
Человек с другой стороны:
- вместо использования монструозных языков программирования я лучше напишу скрипт на простом и универсальном шелле, который будет запускаться везде, а не переживать запуститься ли этот you name it на других системах отличных от моей.
Мой сарказм к тому, что все это лишь инструменты. Да, какой-нибудь новомодный Bosch будет лучше просто молотка. Но бывают моменты, когда нужен именно простой и надежный молоток. А то, что ты можешь им отбить себе палец - уже твои проблемы.
И подобные рассуждения - уровень джуна, который выучил новую фичу и теперь думает что он познал дзен и все знает.
А точно ли он будет запускаться везде? К примеру в линуксе и в маке есть одинаковый набор утилит типа grep, sed и тп но с немного разными возможностями и написать скрипт, одинаково работающий и там, и там - как минимум непросто.
Да, какой-нибудь новомодный Bosch
Начав читать это предложение я уже начал переживать, что новый shell какой-то придумали c интересным названием
— Отсутствие проверок существования каталогов
— Безусловное выполнение rm -rf вместо выполнения с операндом && (cd dir && rm ...) — при отсутствии директории rm выполнится в текущей
— Использование rm с wildcard — можно было бы удалять просто OUT_DIR и создавать её в начале скрипта, как и другие каталоги при их отсутствии
Не догоняю, как скрипт продолжил выполняться? После третьей строки
OUT_DIR=/data/backup/mongod/tmp // 备份文件临时目录
интерпретатор (zsh) останавливается из-за попытки запуска //
с переменной OUT_DIR=/data/backup/mongod/tmp
.
test.sh: 3: test.sh: //: Permission denied
В bash:
test.sh: line 3: /: Is a directory
До запуска rm -rf $OUT_DIR/*
с пустой переменной $OUT_DIR
не доходит.
Всё это попахивает выдуманной историей.
Ссылка на StackOverflow: Deleted database accidentally by a bash script, rescue please
У вас, судя по всему, включен errexit в профиле оболочки, а у китайского разработчика - нет.
По коду сразу понятно, что человек просто не владеет shell скриптом и программирует на другом языке, так не делают люди, которые пишут хорошо скрипты и майтейнерят крупные сервера, программы, и линукс дистрибутивы. Уже не однократно писал на хабре про обработку исключений в shell скриптах, как обычно в скрипте их, отсюда куча проблем. Почему-то в нормальных языках исключения обрабатывают, а в shell про них просто забывают. В shell немного другая логика чем в привычных языках программирования, некоторые вещи с виду и без опыта делаются не удобно и не стоит шуроповертом пытаться забивать гвозди, у bash только одна основная функция автоматизация выполнения команд, куда еще для удобства входят конвеерное выполнение команд и потоковое редактирование. Когда говорят про безопасность bash это такая же ересь, как к примеру сказать, что на R нельзя написать десктоп приложения и синтаксис его не удобен и поэтому язык плохой, там нет безопасности, и он не создан вообще для сложных приложений. Shell скрипт так же как R заточен строго под свои функции и синтаксис их для этого создан. Вы когда нибудь программировали на R?
Вот примерно как делается правильно:
pushd "${TAR_DIR:?}" || (
echo -e "\E[1m\E[31mFailed\E[0m"
exit 1
)
rm -fr tmp
mkdir tmp
popd || (
echo -e "\E[1m\E[31Failed!\E[0m"
exit 1
)
Но ведь shellcheck не серебряная пуля. При желании его можно обмануть. Вопрос в том, что его задача не ловить целенаправленные зловреды, а ловить ошибки и недостатки, сделанные незлономеренно. И даже в этом случае, он не может гарантировать отлов вообще всех проблем. Но лучше уж с ним, чем без него.
Это как раз мой случай безбэкапнойзаботной юности. Только у меня была опечатка в имени переменной. Как известно для оболочки это не ошибка
TIPO='/tmp/dir'
echo ${TIPO}
rm -rf ${TYPO}/*
Единственное замечание шелчека — использовать двойные кавычки с переменной.
In backup.sh line 3:
rm -rf ${TYPO}/*
^-- SC2115: Use "${var:?}" to ensure this never expands to /* .
^-- SC2153: Possible misspelling: TYPO may not be assigned, but TIPO is.
^-- SC2086: Double quote to prevent globbing and word splitting.
Я была не права, не думала что опции могут повлиять на вывод шелчека. Рука не поднялась поставить -rf
, оригинал:
#!/bin/bash
DIR='/tmp/dir'
rm -i "${DIRS}"/*
echo ${DIR}
Спасибо
Shell-скрипт, который удалил базу данных, и история о том, как ShellCheck мог бы помочь это предотвратить