экранирование сложных аргументов командной строки в bash и ssh - PullRequest
2 голосов
/ 19 июня 2019

Я работаю над сценарием bash, чтобы получить время безотказной работы списка серверов. Он просто читает из файла и выполняет удаленную команду на сервере. Возможно, некоторые серверы работали долгое время, а некоторые только что были перезагружены. Я использовал что-то очень простое:

uptime | awk '{print \$2,\$3,\$4}'

Это работает, если сервер работал по крайней мере один день, но если он работал только в течение нескольких часов, выходные данные времени безотказной работы не включают рабочие дни, а просто используют формат час: минута.

Я нашел что-то, что мне очень нравится, но, похоже, не могу избежать этого должным образом в команде ssh, не говоря уже о попытке передать это в сценарии bash:

uptime | awk -F'( |,|:)+' '{d=h=m=0; if ($7=="min") m=$6; else {if ($7~/^day/) {d=$6;h=$8;m=$9} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours,",m+0,"minutes."}'

Я пробовал несколько вещей, но это для меня должно сработать, и я не могу понять, чего мне не хватает:

ssh user@IP "uptime | awk -F'( |,|:)+' '{d=h=m=0; if (\$7==\"min\") m=\$6; else {if (\$7\~\/^day\/) {d=\$6;h=\$8;m=\$9} else {h=\$6;m=\$7}}} {print d+0,\"days,\",h+0,\"hours,\",m+0,\"minutes.\"}'"

Вывод, который я получаю:

awk: {d=h=m=0; if ($7=="min") m=$6; else {if ($7\~\/^day\/) {d=$6;h=$8;m=$9} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours,",m+0,"minutes."}
awk:                                            ^ backslash not last character on line

В конце я пытаюсь поместить это в скрипт bash, который выглядит примерно так:

while IFS= read -r server; do
    ssh -tt user@$server  "uptime command" < /dev/null >> /home/user/uptime
done < "$file"

Ответы [ 2 ]

2 голосов
/ 19 июня 2019

Просто отправьте команды на стандартный ввод ssh:

cat <<'EOF' | ssh user@machine
uptime | awk -F'( |,|:)+' '{d=h=m=0; if ($7=="min") m=$6; else {if ($7~/^day/) {d=$6;h=$8;m=$9} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours,",m+0,"minutes."}'
EOF
1 голос
/ 19 июня 2019

Мне кажется, что вы слишком много избегаете:

ssh user@IP "uptime | awk -F'( |,|:)+' '{d=h=m=0; if (\$7==\"min\") m=\$6; else {if (\$7~/^day/) {d=\$6;h=\$8;m=\$9} else {h=\$6;m=\$7}}} {print d+0,\"days,\",h+0,\"hours,\",m+0,\"minutes.\"}'"

Я получаю:

6 days, 11 hours, 21 minutes.

Обновление:

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

command="uptime | awk -F'( |,|:)+' '{d=h=m=0; if (\$7==\"min\") m=\$6; else {if (\$7~/^day/) {d=\$6;h=\$8;m=\$9} else {h=\$6;m=\$7}}} {print d+0,\"days,\",h+0,\"hours,\",m+0,\"minutes.\"}'"
ssh user@IP1 "$command"
ssh user@IP2 "$command"

Тестовый прогон:

$ bash script.sh
0 days, 2 hours, 26 minutes.
7 days, 4 hours, 18 minutes.

Подождите, есть еще:

Мне часто нужно отправлять несколько команд на удаленные хосты: для этого я нахожу цитируемый синтаксис heredoc , предложенный Чороба в его ответе , чтобы быть наиболее удобным.

command=$(cat <<'EOF'
hostname
uptime | awk -F'( |,|:)+' '{d=h=m=0; if ($7=="min") m=$6; else {if ($7~/^day/) {d=$6;h=$8;m=$9} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours,",m+0,"minutes."}'
EOF
)
ssh user@IP1 "$command"
ssh user@IP2 "$command"

Это вывод:

$ bash script.sh
server1
0 days, 2 hours, 26 minutes.
server2
7 days, 4 hours, 18 minutes.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...