Очистка ошибок для сценариев оболочки

Предполагая, что ваш файл почтового ящика находится в формате mbox, вы можете использовать утилита formail , которая поставляется с procmail, для запуска команды для каждого письма с параметром -s , чтобы сообщить ему, что ввод - это почтовый ящик, а не просто отдельное письмо.Эта команда может быть procmail , если вы хотите применить свои правила procmail, или любой другой командой, которая принимает почту на стандартный ввод и делает с ней все, что захочет.

formail -s procmail <Mboxrd && mv Mboxrd Mboxrd.done

Другой подход - загрузить почтовый ящик в Mutt и применить некоторые макросы. Это имеет то преимущество, что оно не зависит от формата почтового ящика, но имеет недостаток, заключающийся в том, что макросы mutt могут быть загадочными (хотя не обязательно более загадочными, чем правила procmail). Еще одно преимущество использования mutt заключается в том, что он может перемещать по одному письму за раз, поэтому, если оно прервано на полпути, оно может возобновиться с того места, где оно было остановлено.

2
13.07.2017, 10:48
2 ответа

Лично я бы выбрал вложенный if then, так как его было бы легче читать и поддерживать. Однако, если у вас много уровней вложенности, вы можете попробовать что-то вроде этого (Я поставил префикс echoдля тестирования):

#!/bin/bash
run1(){ echo mount a x;}
run2(){ echo mount b y;}
run3(){ echo setup_thing;}
run4(){ echo mount c z;}
run5(){ echo do_something;}

undo5(){ :;}
undo4(){ echo umount z;}
undo3(){ echo cleanup_thing;}
undo2(){ echo umount y;}
undo1(){ echo umount x;}

for i in {1..5}
do      run$i
        code=$?
        [ $code != 0 ] && break
done
let i=i-1
while [ $i -gt 0 ]
do      undo$i
        let i=i-1
done
exit $code

Я сохранил функции запуска и отмены в порядке вашего примера, но вы могли бы выиграть, разместив их ближе друг к другу:

run1(){  mount a x;}
undo1(){ umount x;}
run2(){  mount b y;}
undo2(){ umount y;}
run3(){  setup_thing;}
undo3(){ cleanup_thing;}
...

Вместо нумерации функций 1,2,3... вы можете назвать функции выполнения как угодно и перечислить имена в нужном вам порядке. Добавьте согласованный префикс для функции отмены, чтобы упростить ее :

.
mnta(){... }
undomnta(){... }
mntb(){... }
undomntb(){... }

order='mnta mntb...' toundo=
for i in $order
do      $i
        code=$?
        [ $code != 0 ] && break
        toundo="undo$i $toundo"
done
for i in $toundo
do  $i
done

Или вы действительно можете использовать trap, но настроить его только один раз с помощью trap mytrap exitи использовать глобальную переменную для хранения того, что нужно очистить, и просто добавлять к этому на каждом шагу:clean="1 $clean". Затем функция mytrapбудет просто перебирать значения в $clean.

0
27.01.2020, 22:39

Обычно используется trapдля отмены всего, когда вы закончите. Он должен быть идемпотентным, т. е. он должен изящно завершиться ошибкой, если некоторые из шагов не могут быть выполнены.

#!/bin/bash

clean_up=false
errorhandler () {
    umount z || true
    $clean_up && cleanup_thing
    umount y || true
    umount x
}
trap errorhandler ERR EXIT

mount a x
mount b y
setup_thing
clean_up=true
mount c z
do_something

Обратите внимание, что ловушка также срабатывает на EXIT, поэтому она также будет выполняться до нормального завершения сценария; так что вам вообще не нужно очищать явно.

Я полагаю, что сигнал ERRпсевдо -является расширением Bash. Так что это не будет работать в Ash/Dash/устаревшей оболочке Bourne и т. д.

3
27.01.2020, 22:39

Теги

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