Как мне сделать это в сценарии оболочки:
for (int i=0;i<1000;i++) {
run applicationA
run applicationB
if (retvalFromApplicationB!=0) {continue;}
else {pipe ouptut (stdout) from applicationB to (stdin of) (and start) applicationC}
if (retvalFromApplicationC!=0) {break;}
}
Я использую Ubuntu
#! /bin/sh -
i=0; while [ "$i" -lt 1000 ]; do
cmdA
cmdB > tempfile || continue
cmdC < tempfile || break
i=$((i + 1))
done
rm -f tempfile
Если вы не можете засорять текущий каталог временными файлами, вы можете сделать:
#! /bin/sh -
i=0; while [ "$i" -lt 1000 ]; do
cmdA 3>&- 4<&-
tmp=$(mktemp) || exit
exec 3> "$tmp" 4< "$tmp"
rm -f "$tmp"
cmdB >&3 3>&- 4<&- || continue
cmdC <&4 3>&- 4<&- < tempfile || break
i=$((i + 1))
done
exec 3>&- 4<&-
rm -f tempfile
Что бы вы ни делали, вам нужно где-то сохранить этот вывод, так как вы не можете получить статус выхода cmdB
, пока он закончился.
Вместо этого вы можете сохранить его в памяти. Если вывод cmdB
является текстом, вы можете сделать:
#! /bin/sh -
i=0; while [ "$i" -lt 1000 ]; do
cmdA
output=$(cmdB > tempfile && echo .) || continue
output=${output%.}
printf %s "$output" | cmdC || break
i=$((i + 1))
done
Если printf
не встроен в ваш / bin / sh
(например, если вы ' Мы установили mksh
или yash
и сделали его sh
), что приведет к сбою при выводе размером более 128 КБ.
Или вместо этого вы можете использовать perl
:
#! /usr/bin/perl
for ($i = 0; $i < 1000; $i++) {
system "cmdA";
$output = `cmdB`;
next if $?;
open TO_C, "|-", "cmdC" or last;
print TO_C $output;
close TO_C;
last if $?;
}
Я бы добавил, что если ваша оболочка - bash, тогда $? также доступен. На странице руководства: «Расширяется до состояния последнего выполненного конвейера переднего плана», что означает, что он содержит статус выхода последнего выполненного процесса.
#!/bin/bash
for (int i=0;i<1000;i++)
{
run applicationA
retvalFromApplicationA = $?
run applicationB
retvalFromApplicationB = $?
if (retvalFromApplicationB!=0) {continue;}
else {pipe ouptut (stdout) from applicationB to (stdin of) (and start) applicationC}
if (retvalFromApplicationC!=0) {break;}
}
Приведенный выше код не фиксирует статус выхода applicationC, но это будет примерно так:
applicationB | applicationC
if [ $? -eq 0 ]; then ...
Это работает, потому что последним процессом, который завершится, будет applicationC. Если вы используете другую оболочку, проверьте страницу man / info. Есть и другие способы сделать это с помощью && и || операторы тоже.