Удаленный запуск нескольких команд с помощью скрипта bash

Удаленный запуск нескольких команд с помощью скрипта bash

Мне нужно войти на удаленные серверы через ssh и перейти в папку tmp, а там запустить команду rm. Но когда я запускаю скрипт ниже, он переходит на удаленный сервер, но не переходит в папку temp и не запускает команду rm.

#!/bin/bash
for i in `cat list`
echo $server
echo "------------------------------------------"
ssh $server << MYCOMMANDS
cd /tmp
rm log52.log
MYCOMMANDS

решение1

Единственная реальная проблема с вашим кодом заключается в том, что в вашем цикле отсутствуют doи done, что приведет к синтаксическим ошибкам, а также в том, что вы используете iв качестве переменной цикла , но пытаетесь соединиться с какой-то serverпеременной, которая вполне может быть неустановленной.

Кроме того, вы используете catв команде подстановку без кавычек, котораяв целомплохая идея, если вы не знаете наверняка, что будете читать строки без пробелов и символов подстановки имен файлов (хотя большинство имен хостов ведут себя в этом отношении хорошо).

В большинстве случаев лучше читать входные данные построчно, например так:

while IFS= read -r remote; do
    ssh -n "$remote" 'rm -f /tmp/log52.log'
done <list

Я использую ssh -nздесь, чтобы остановить sshчтение его стандартного входного потока (который был бы подключен к listфайлу). Без -n, sshбудет прочитано оставшееся содержимое listи ваш цикл будет выполнять только одну итерацию.

В качестве альтернативы, если вы действительно хотите прочитать команды из документа here-document:

while IFS= read -r remote; do
    ssh -T "$remote" <<'END'
rm -f /tmp/log52.log
END
done <list

Здесь я использую ssh -Tдля явного отключения выделения псевдотерминала, что не нужно, поскольку мы не делаем ничего, что требует взаимодействия с пользователем. Я делаю это, поскольку sshзаметит, что его стандартный поток ввода содержит данные, поэтому он предупредит нас об отсутствии функционирующего терминала на удаленной системе для выполнения интерактивных действий. Здесь нам не нужно -nwith ssh, поскольку мы переназначаем стандартный поток ввода для sshfrom here-document.

Но цикл можно заменить одной командой

xargs -I {} ssh {} 'rm -f /tmp/log52.log' <list

... где xargsутилита будет читатьлиниииз файла list, замените {}в sshкоманде строку, считанную из файла, и выполните действие доступа к удаленным системам для удаления определенного файла. Я использую, rm -fчтобы не вызывать ошибку, если нет файла для удаления.

Некоторые реализации xargsпозволяют выполнять утилиту параллельно, например, с помощью -P 4(что позволит sshодновременно выполнять не более четырех команд).

решение2

#! /bin/bash
for i in `cat list`
do
    echo $i
    echo "-------------------------"
    ssh $i "rm /tmp/log52.log"
done

Если вам нужно удалить только один файл, вы можете просто указать это в одной строке. Кроме того, вам может быть полезно добавить -fв rm.

решение3

Вы не можете просто перенаправить stdin сеанса ssh таким образом. Вы должны увидеть сообщение об ошибке, похожее на:

Псевдотерминал не будет выделен, поскольку stdin не является терминалом

Вам нужно использовать опцию -tt для ssh, чтобы принудительно выделить псевдотерминал. Попробуйте это:

#!/bin/bash
for i in `cat list`
echo $server
echo "------------------------------------------"
ssh -tt $server << MYCOMMANDS
cd /tmp
rm log52.log
MYCOMMANDS

Связанный контент