Как передать команду только в случае сбоя другой команды (с сохранением исходного ввода )?

Только что получил ответ от команды Real VNC. По-видимому, параметры SendPrimary были доступны только в версии Linux VNC Viewer. Однако, наконец, он был перемещен на сервер VNC. Поэтому, чтобы отключить параметр SendPrimary, вам нужно добавить следующую строку в.vnc/config.d/vncserverui -virtual:

SendPrimary=0

Если вы хотите отключить его глобально, добавьте его в/etc/vnc/config.d/common.custom.

Изменить:Обратите внимание, что вам необходимо перезапустить VNC-сервер, чтобы это вступило в силу.

1
22.12.2020, 00:15
3 ответа

Добро пожаловать в Stack Exchange! Здесь много хорошей информации. Спасибо за вашу должную осмотрительность в первую очередь.

Проблема, которую я вижу в вашей команде, заключается в том, что она «напрашивается вопрос». Другими словами, предполагается, что вы знаете ответ еще до того, как начнете.

Давайте посмотрим поближе :cat file.txt
Содержимое "file.txt" будет отправлено в STDOUT.
Если команда «cat» выдает какие-либо ошибки, они будут относиться к STDERR.
ПОСЛЕ завершения команды устанавливается код выхода. 0 = успех; все остальное - ошибка.

Проблема здесь в том, что вы не знаете, следует ли вам выполнить command1или command2, пока вывод не будет отправлен. Что значит, пропало.

Сравните это с этим:
cat file.txt | sort
Фактически это 2 команды:
1:cat file.txt 1> temp_file
2:sort < temp_file
Хорошо, не НАСТОЯЩИЕ команды Unix, сделанные таким образом для пояснения.
1 :Отправьте STDOUT в "tempfile" (, который является частью 1> ). Также отправьте STDERR на консоль.
2 :Запустите команду sort и прочитайте STDIN из "tempfile".
Помещение канала |между двумя командами устраняет необходимость во временном файле. Канал означает :перенаправление STDOUT с «cat» на STDIN «sort».

Ваша проблема:
Вы хотите перенаправить STDOUT на STDIN другой команды, но вы еще не знаете, что это за команда, поэтому вы не можете ее перенаправить.

Прежде чем я перейду к возможному решению, позвольте мне дать вам небольшую предысторию:
В Unix есть способ выполнить команду так, как вы хотите. А именно:
my_command argument1 argument2 && echo "Success" || echo "Failure"

После того, как my_commandзапустит (и вернет свой статус выхода )с STDOUT и STDERR на консоли,запустить то или иное эхо.
&&означает «Сделайте это, если последняя команда была успешной»
||означает «Сделать это, если последняя команда не удалась»

Вы очень близки со своей первоначальной командой. У вас есть:
cat file.txt | command1 || command2
Давайте изменим это на это:
cat file.txt && command1 || command2
Это дает вам все, что вы хотите, кроме вывода.

Вопрос 1:
Если cat file.txtработает, то должен ли command1читать STDOUT и игнорировать STDERR?
Точно так же, если это не удается, следует ли command2читать STDERR и игнорировать STDOUT?
Или любая из команд должна читать как STDOUT, так и STDERR?

Я отвечу на оба вопроса для полноты.
В любом случае вам понадобится способ сохранить вывод для последующей обработки. Обычно это временный файл _.

Захват STDOUT и STDERR в одном временном _файле:
cat file.txt > /tmp/temp_file 2>&1

Захват STDOUT во временный файл _#1 и STDERR во временный файл _#2:
cat file.txt > /tmp/out_file 2 >/tmp/err_file

Вопрос 2:
Разрешают ли command1и/или command2указывать имя файла в командной строке?
command1 temp_file

Разрешают ли command1и/или command2перенаправление из файла?
command2 < temp_file

command1и/или command2считывают STDIN?
cat temp_file | command1

Примечание. :Примером может служить команда Word Count.
wc temp_file
cat temp_file | wc
wc < temp_file
Вторая форма может быть проблематичной в && || форма. Я включаю его сюда для полноты картины.

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

Теперь мы можем объединить их вместе:
cat file.txt > /tmp/out_file 2>/tmp/err_file && command1 < /tmp/out_file || command2 < /tmp/err_file

Затем удалите временные файлы:
rm /tmp/out_file /tmp/err_file

Это должно дать вам то, что вы хотите.
Я уверен, что другие гуру могут придумать способ не использовать временный файл _. Мне нравится делать вещи простыми и понятными, потому что я не работаю в магазине программирования и понятия не имею, кому придется поддерживать мой код.

2
18.03.2021, 22:41

Я думаю, что единственный способ сделать это — записать вывод command1в файл и прочитать его вcommand2:

set -o errexit
command1 < file.txt > 1.out
command2 < 1.out

В качестве альтернативы

if command1 < file.txt > 1.out
then
    command2 < 1.out
fi

Конечно, на данный момент преимущества асинхронной обработки конвейера исчезают.

1
18.03.2021, 22:41

Проще всего сохранить файловый поток в file, а затем

command1 < file || command2 < file

или

if command1 < file; then
    echo 'first command was successful'
else 
    command2 < file
fi

или любой подобный синтаксис, в зависимости от того, что вы хотите вывести.

Если вы хотите, чтобы один и тот же файловый поток использовался двумя командами одновременно, вы должны использовать что-то вроде teeили любой другой подобный подход, что означает, что либо command2должен начать обработку до того, как command1вернется, либо следует использовать какую-то буферизацию, возможно, вместе с некоторой сигнализацией. Хорошая и масштабируемая буферизация — это файл на диске.

1
18.03.2021, 22:41

Теги

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