У меня есть входной файл, который имеет следующие данные:
driver2:y
driver5:y
driver3:n
driver1:y
driver4:y
Требование состоит в том, что для каждого драйвера, если значение равно "y", сценарий должен проверить наличие набора файлов, связанных с этим драйвером. Если все они существуют, то следует выполнить следующий шаг, связанный только с этим драйвером.
Основной скрипт читает строку за строкой из файла input.txt. и я использую CASE для этого.
Моя проблема заключается в том, что когда я пытаюсь вызвать функцию function_exists() из логики CASE (которая, как вы можете видеть, прокомментирована в сценарии), или если я использую какие-либо условия "IF" вместо function_exists() для выполнения той же проверки, этот конкретный часть логики CASE выполняется (скажем, driver2, выполняется весь код в разделе «driver2)»), и управление сценарием автоматически выходит из логики CASE, и сценарий завершается, не читая оставшиеся строки из входного файла.
Сценарий читает все записи, но что-то не так с логикой CASE, когда я использую функции и условия IF.
Я не могу понять, что пошло не так со сценарием, какую ошибку я здесь делаю. Может кто-то помочь мне с этим?
#!/bin/sh
function_exists ()
{
ssh $remote_server "test -e $1"
if [ $? == 0 ]
then
echo "file found : $1"
else
echo "file not found : $1"
fi
echo "***** exiting function"
}
remote_server = "vmlinux1"
input = "input.txt"
while IFS= read -r line
do
IFS = ":"
read -ra arr <<< "$line"
driver=${arr[0]}
export driver=$driver
driverInstall=${arr[1]}
echo "read value" $driver $driverInstall
if [ $driverInstall == 'y' ]; then
case $driver in
driver1)
echo "entered driver 1"
#function_exists /opt/installer/file1.txt
echo "***** control came back to $driver"
;;
driver2)
echo "entered driver 2"
#function_exists /opt/installer/file2.txt
echo "***** control came back to $driver"
continue
;;
driver4)
echo "entered driver 4 - for directory check"
#function_exists /opt/installer/directory1
echo "***** control came back to $driver"
;;
*)
echo "${driver} - NOTHING DEFINED"
;;
esac
else
echo "${driver} - SKIPPED "
fi
done < "$input"
echo "Script ended
======================================= = "
Подключите стандартный ввод «ssh» к nirvana, иначе ssh съест оставшиеся строки.
ssh $remote_server "test -e $1" < /dev/null
# you can also use ssh -n
read value driver2 y
entered driver 2
file not found : /opt/installer/file2.txt
***** exiting function
***** control came back to driver2
read value driver5 y
driver5 - NOTHING DEFINED
read value driver3 n
driver3 - SKIPPED
read value driver1 y
entered driver 1
file found : /opt/dev/python/scrapper/main.py
***** exiting function
***** control came back to driver1
read value driver4 y
entered driver 4 - for directory check
file not found : /opt/installer/directory1
***** exiting function
***** control came back to driver4
Script ended
========================================
The problem is that your script runs ssh commands and by default ssh reads from stdin which is your input file. As a result, you only see the first line processed, because the command consumes the rest of the file and your while loop terminates.
This happens not just for ssh, but for any command that reads stdin, including mplayer, ffmpeg, HandBrakeCLI, and more.
To prevent this, pass the -n option to your ssh command to make it read from /dev/null instead of stdin. Other commands have similar flags, or you can universally use < /dev/null
Превосходно. Большое спасибо. это сработало. Я застрял с этим больше дня и пробовал несколько вещей. Не подскажете, где я могу узнать об этом подробнее? Я не нашел момент, которым вы только что поделились, нигде в книгах или на учебных сайтах.
@Курк: chengweiyang.cn/2014/09/25/SSH-есть-stdin-в-пока-петля
Другим разумным подходом является чтение цикла while из другого файлового каталога. например while IFS=: read driver driverInstall <&3; do ... done 3< "$input"
Вместо того, чтобы коряво парсить строку после того, как вы ее прочитали, вы можете парсить ее, пока читаете, с помощью
while IFS=: read driver driverInstall; do ...