Ну давайте разберем
if ./script.sh - если при выполнении script.sh все нормально
then - то ничего не делаем
else ./script.sh - иначе выполняем script.sh
fi - финиш
stderr - это поток вывода - туда можно писать, но никого это ни к чему не обязывает. любой процесс завершается с каким-то кодом возврата. по умолочанию все шелы считают 0 - без ошибок, не 0 - с ошибками. некоторые утилиты в код возврата пишут код ошибки некоторые нет. проверить код возврата последней команды можно через $?. в скриптовах для выхода с определенным кодом возврата нужно использовать exit (man 1 exit).
>Но вот только ваше решение никак не отслеживает ошибки.
если вы про ./script.sh || ./script.sh, то все он отслеживает. Схема тут простая. в bash (как и много где еще) логические выражения оптимизируются. то есть если на каком-то этапе становится понятно какое значение будет иметь данное выражение - то дальнейшее его вычисления прекращаются. в данном случае, если первый вызов скрипта завершится с 0 (true) то и все ворожение будет иметь значение true и по этому второй раз скрипт не запускается. если же первый вызов завершается с false то еще не понятно какое значение получится и для этого запускается вторя часть.
>А на счет кода возврата, не понял наезда. Чем вас мой вариант ответа не устроил?
>Как и все в линукс, через stderr
Еще раз stderr - это поток вывода, такой же как stdout (ну почти такой же). Туда можно писать что угодно, но о том с ошибкой завершился процесс или нет это не говорит