Мы можем указать нашим сценариям останавливаться при обнаружении проблемы с помощью директивы «set -euo pipefail».

В прошлых статьях мы представили несколько небольших примеров Bash-скриптов: что это такое, как зацикливаться и как проверять условия. Последняя тема очень важна, так как позволяет сделать наши скрипты более безопасными. К сожалению, проверка всех возможных ошибок занимает много времени, и чем больше if условий мы должны написать, тем больше ошибок мы закончим, чтобы добавить к нашим сценариям.

Вот почему, прежде чем перейти к дальнейшим темам сценариев Bash, я хотел бы представить сеть безопасности, чтобы предотвратить некоторые распространенные ошибки.

Следующий скрипт представляет собой гипотетический конвейер, который проходит через файлы .fastq, обрезает, выравнивает и, наконец, преобразует выровненный файл SAM в BAM¹.

Что может пойти не так?

  • Во-первых, есть опечатка: мы делаем вид, что выравниваем $IPUT вместо $INPUT. Поскольку переменная никогда не была объявлена, Bash не найдет никакого значения и передаст bwa"trimmed_" в качестве имени файла. Этого не существует.
  • Предположим, что мы переместили ссылку. Переменная действительна и содержит значение, но программа bwa не может выполнить выравнивание и завершится ошибкой. Обнаружить ошибку не так-то просто: скрипт продолжит работу и конвертирует пустой SAM-файл в BAM…

Две проблемы: использование неинициированных (таким образом, пустых) переменных и отсутствие остановки выполнения скрипта в случае сбоя программы.

Как мы можем решить эти проблемы?

Добавление одной строки в начало скрипта (сразу после шебанга):

set -euo pipefail

Эта инструкция² приведет к сбою сценария и завершению работы при обнаружении одной из вышеуказанных проблем. В частности, используются переключатели:

  • -e приведет к завершению работы сценария в случае сбоя одной программы.
  • -o, если вы используете каналы (мы делали это в прошлых статьях), -e будет запускаться только в случае сбоя последней программы канала. С -o также будет проверено другое.
  • -u для несвязанных переменных. Когда это добавлено, если переменная не была объявлена ​​​​ранее, сценарий завершится ошибкой.
  • -x, это не указано в примере, но может быть полезно в некоторых случаях: это заставит скрипт печатать каждую команду перед ее выполнением. Полезно при отладке или тестировании скриптов.

В нашем скрипте все еще есть нерешенная проблема: *.fastq будет расширен только в том случае, если у нас есть хотя бы один файл .fastq в нашем текущем каталоге. В последней статье мы представили оператор if для проверки этой проблемы, поэтому мы могли бы применить ту же стратегию и здесь.

Существует более короткое и, возможно, более красивое решение, которое будет применяться ко всему сценарию:

shopt -s failglob

Это директива, которая, подобно «set -euo pipefail», будет активна на протяжении всего скрипта и вызовет сбой скрипта при сбое расширения оболочки.

Проверить, установлена ​​ли переменная

Если вы используете переключатель -u и не определили переменную, проверка наличия у нее значения приведет к завершению сценария, если только вы не проверите его с помощью следующего синтаксиса:

Защитная сетка усложняет жизнь

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

Представлено на лекции по метагеномному анализу, La Sapienza — Рим, декабрь 2018 г.

¹ Да, команды «TrimReads» и «AlignReads» являются вымышленными.

² См. эту страницу для получения дополнительной информации о наборе.