Сценарий Bash застревает во время выполнения

У меня есть сценарий bash, который читает CSV файл, содержащий source IP адрес, destination IP адрес destination port .

Мой скрипт в основном выполняет 2 теста:

1 Производительность 2.

В тесте производительности я копирую файлы из source в destination (используя scp ) для вычисления сетевого ввода-вывода. После этого копирование одного и того же файла из одного места сервера назначения в другое место на целевом сервере для вычисления дискового ввода-вывода.

В рамках теста подключения я делаю nc из source в destination чтобы проверить, открыт ли port .

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

Здесь я не могу понять, почему он застревает, и даже поведение несовместимо, каждый раз, когда он застрял в другом месте сценария.

Пожалуйста, помогите мне в решении этой проблемы. При необходимости я могу опубликовать свой полный скрипт здесь.

Обновить :

Наблюдение: Другое, что я заметил, если я не нажимаю Ctrl + C, тогда скрипт возобновляется автоматически через 5 минут.

Часть реального скрипта, где он застревает.

 #Connectivity Test TMP=$(mktemp) nc -z -v -n $lastDestinationIP $port >\$TMP if grep -q "succeeded" <<< cat echo \$TMP;then echo $x','$lastSourceIP','$lastDestinationIP','$sourceFqdn','$fqdn','$port',Connectivity,NA,NA,NA,Pass,'$(date) | ssh $username@$baseLocation 'cat >> report.txt' else echo $x','$lastSourceIP','$lastDestinationIP','$sourceFqdn','$fqdn','$port',Connectivity,NA,NA,NA,Fail,'$(date) | ssh $username@$baseLocation 'cat >> report.txt' fi rm $TMP fi exit ENDSSH 

Большую часть времени он застревал при вызове выхода.

Вот фрагмент, где он застрял большую часть времени (с консоли).

 21 14:48:16 EDT 2014 | ssh puppet-admin@10.XX9 'cat >> report.txt','Fri Mar > fi > > #rm KB_33.txt > #rm MB_10.txt > #rm MB_100.txt > rm -rf dummy > else > #Connectivity Test > nc -z -v -n -w 2 10.XX17 1524 >/tmp/tmp.GJ1knZF5Jn > if grep -q "succeeded" <<< cat echo /tmp/tmp.GJ1knZF5Jn;then 21 14:48:16 EDT 2014 | ssh puppet-admin@10.XX9 'cat >> report.txt','Fri Mar > else 21 14:48:16 EDT 2014 | ssh puppet-admin@10.XX9 'cat >> report.Fail,'Fri Mar > fi > fi > exit > 

Вот короткий и сладкийheredoc – это в основном файл, передаваемый в файловый дескриптор.

Большинство людей не обозначают 0<<descriptor и поэтому вы получаете его на <&0 stdin. ssh <&0 stdin. ssh передает stdin в вызываемый процесс, поэтому, если вы передаете ему heredoc он будет проходить через вход в вызываемую удаленную оболочку.

Единственное особое качество в отношении heredocs – это разница между \"'quoted и unquoted heredoc LIMITER. Таким образом, <<'THIS' отличается от « <<THIS. Когда вы не цитируете LIMITER, содержимое здесь-документа оценивается для ${shell:+expansion} . Как только один проход ${shell:+expansion} завершен, осталось совсем немного отличить здесь-документ от любого другого файла, поданного как <~/input .

Например:

 cat <<\QUOTED >~/file $(echo "This is ${NOT:-} expanded.") #END QUOTED cat <~/file > $(echo "This is ${NOT:-} expanded.") > #END 

Но…

 cat <<UNQUOTED >~/file $(echo "This is ${NOT:-} expanded.") #END UNQUOTED cat <~/file > This is expanded. > #END 

Вы продолжаете использовать bash <<< herestring с cat. Я точно не знаю, как работает herestring но я готов поспорить, что cat's уже задействована. Поэтому cat объединяет свой <&0stdin со своим stdout>&1 . Это все, что он делает. Таким образом, вы излишне усложняете <<STDIN когда вы <<< cat его.

Это может быть реальной проблемой, если cat начнет потреблять входной поток, который вы не намерены его потреблять. Запустите только % cat на вашем терминале, и это будет выглядеть так, как будто ничего не происходит, потому что stdin и stdout терминала – это один и тот же файл – ваш $(tty) . Но когда они различаются, cat все равно их объединяет, и это может стать довольно грязным, если вы не хотите, чтобы это произошло.

Мне кажется, что некоторые \'quotes пропускают расширение, когда $(date) $expanded . Тогда возможно : null shell builtin вызывается и |piped на следующую неуказанную команду после ssh которая будет cat >> report.fail которая не должна генерировать ничего вообще в этом файле. Итак, cat >>appending /dev/null к report.fail , так как она может выдержать ее, я думаю. Или, что более вероятно, до тех пор, пока exit разрешает ssh переносить null stream.

Кроме того, вы проверили, есть ли у вас буквальный $TMP в текущем рабочем каталоге? Я вижу ENDSSH внизу, который выглядит как heredoc LIMITER для меня, поэтому я считаю, что это не весь скрипт или он был отредактирован по ошибке. Было бы разумно, если бы тело heredoc использовало \$TMP, но, как я думаю, nc сначала будет >truncate затем записать его stdout в файл с именем $TMP. Опять же, я думаю, вы все равно, так что, возможно, вы просто не заметили.

И поскольку вы используете $TMP вы, возможно, не поняли, что кто-нибудь задаст этот вопрос:

Как работает $(mktemp) для вас без аргумента filename.xxx ?

ОБНОВЛЕНИЕ Я посмотрел ближе к вашему выводу, и определенно >/tmp/tmp.GJ1knZF5Jn означает, что работает $(mktemp) – даже часть \$TMP . Поэтому вы только что научили меня, что мне нужно указать mktemp .xxx если я укажу имя файла вообще. Спасибо.

Тем не менее, я думаю, что где-то наверху есть heredoc? Это может быть не так, и \\ – это только попытка справиться с побочным эффектом echo \$TMP <<<herestring, но я не знаю … Интересно.

Я не знаю, полностью ли я прав, потому что не знаю, откуда взялись все эти переменные. Но это близко к тому, как я это сделаю:

(что фактически делает последние два вопроса неактуальными в любом случае)

 _ssh() ( ssh "$1"@"$2" 'printf %s, `cat` >> '"$3" ) <<-PARAMS "$lastSourceIP" "$lastDestinationIP" "$sourceFqdn" "$fqdn" "$port" " "ConnectivityNA" "NA" "NA" "Pas" "$(date)" PARAMS nc -z -v -n $lastDestinationIP $port |\ grep -q "succeeded" && suffix=txt _ssh user host report.${suffix:-fail} unset suffix ?ENDSSH? 

Примечание: "$quotes" в приведенном выше случае предназначены для использования printf's с другой стороны процесса ssh – ни для чего другого. Эти "quotes" остаются такими же, как и после оценки всех вышеуказанных PARAMS .

Там кое-что происходит, что я уже рассмотрел раньше. Например, func() ( scope ) мне нравится думать, здесь был закрыт . Здесь также был рассмотрен ${parameter:-expansion} , но также продемонстрирован довольно хорошо здесь и здесь . Я попал в какой-то странный материал heredoc здесь , здесь и здесь . Наверное, есть и другие. Думаю, мне нравится испортить мою оболочку или что-то в этом роде.

В этом случае, однако, используя функцию и heredoc, как я, cat не может застрять. PARAMS отправляется как stdin и cat уйдет, когда достигнет EOF (или CTRL-D ), так как он будет потреблять PARAMS он будет останавливаться каждый раз. Это особенно важно, если вы используете это в heredoc который также находится на <&0 потому что PARAMS будет стоять на пути, когда cat ест ваш скрипт в середине исполнения.

В любом случае, надеюсь, это поможет. Если я что-то пропустил, не стесняйтесь спрашивать.