У меня есть if
заявление для расчета файлов и удаления всех, кроме последних трех файлов. Но я хочу запустить эту команду удаленно. Как я могу сочетать ssh
с if
условием?
Я попробовал это, но безуспешно.
#!/bin/bash
ssh -t test@192.168.94.139 "cd /var/www/test.com/backup ;
if [ $(ls | wc -l) -lt 3 ]
then
echo "Less"
else [ $(ls -t *.tgz|awk 'NR >3'|xargs rm -f) ]
echo "deleted"
fi"
Ошибка, которую я получил:
ls: не может получить доступ * .tgz: нет такого файла или каталога
command-line
bash
ssh
Janith
источник
источник
$(
)
Часть команды выполняются локальной оболочкой , прежде чем он даже начинаетssh
команду. Это верно как в$(
)
одиночку, так и в том случае, если оно заключено в"
s. Однако если бы он$(
)
был внутри'
s, он не был бы выполнен локальной оболочкой.Ответы:
ПРИМЕЧАНИЕ: на самом деле здесь два вопроса. Один из них: «Я хочу выполнить нетривиальную задачу на удаленном сервере, доступном через SSH». Другой - «Я пытаюсь передать сложную строку команде, и аргумент в конечном итоге отличается от того, что я намеревался». Я отвечаю на вопрос низкого уровня, не обсуждая, является ли используемый подход «правильным» (удобный, не подверженный ошибкам, безопасный и т. Д.) Для решения высокого уровня. Как указано в других ответах и комментариях, вполне возможно, что нет.
Ваша командная строка в основном правильная; вам нужно только немного изменить цитату.
Основная проблема заключается в том, что строки в двойных кавычках расширяются вашей локальной оболочкой, и поэтому
$(...)
части будут оцениваться в вашей локальной системе. Чтобы передать их в удаленную систему, вы должны заключить скрипт в одинарные кавычки.У вас также есть некоторые кавычки. В вашем оригинальном сценарии есть аргументы для двух
echo
s; если вы измените внешнюю цитату на одинарную, то это будет скрипт awk. Это эффективно приводит к тому, что кавычки опускаются, что не беспокоитecho
s, но это испортит скрипт awk, так как знак больше чем станет перенаправлением вывода. Поэтому после изменения внешних кавычек на одинарные кавычки измените их на двойные.Это ваш скрипт с исправленной цитатой. У скрипта могут быть другие проблемы, я просто исправил синтаксис.
источник
/var/www/test.com/backup
переменную с именем "BACKUPDEST" иcd $BACKUPDEST
можете ли вы сказать мне, как это сделать?BACKUPDEST
? Если это происходит на удаленной стороне, просто включите его в скрипт как обычно. Если вы хотите установить его локально (например, рассчитать его в локальном скрипте или передать в качестве аргумента командной строки), вы можете изменить первую строку на например:"cd $BACKUPDEST"' ;
- оболочка расширяет часть в двойных кавычках, сохраняет одинарные в кавычках part intact, объединяет их и передает результат в качестве последнего аргументаssh
."cd '$BACKUPDEST'"' ;
в случае, если путь в этой переменной содержит некоторые странности (например, пробел). Опять же: просто сказать, что это можно сделать таким образом, а не то, что это должно быть сделано таким образом.Да, вы можете выполнить сложные сценарии через
ssh
В этом примере для создания командной строки используется документ bash here . В любом случае, передача сценариев через ssh подвержена ошибкам, поскольку сложное цитирование и экранирование переменных затруднены (обратите внимание на обратную косую черту перед командами). Если скрипт становится слишком сложным, лучше скопировать его через,
scp
а затем выполнить на целевом хосте.Я не пытался исправить ваш скрипт , но вот пример того, как может работать подсчет и удаление на удаленном хосте:
Это
ls -t *.tgz
не сработает, поскольку глобализация происходит только в локальной системе. Кроме того, используяls
для подсчета файлов не является хорошей идеей, поскольку она также возвращает запись , как.
,..
и каталоги.источник
syntax error near unexpected token elif'
,elif [ $(ls -t |awk 'NR >3'|xargs rm -f) ]; then'
;
первом заявлении пропало без вести. Но я не исправил тебе скрипт! Есть еще много вопросов, напримерls *.tgz
$(...)
внутри строки в двойных кавычках, поэтому локальная оболочка оценила ее. Экранирование, как\$(...)
показано в первом примере, или использование одинарных кавычек вокруг всего сценария предотвращает его расширение локальной оболочкой, поэтому он отправляется в удаленную систему, расширяется удаленной оболочкой и сценарий работает. как предполагалось.printf
расширять переменные - с этим все равно будет легче справиться, чем пытаться экранировать все переменные оболочки. Кроме того, это позволит избежать необходимости использоватьcat
просто для захвата здесь документ в переменную!Я думаю, что вся эта сложная цитата является достаточным доказательством, чтобы не использовать ее, а вместо этого использовать скрипт. Если вы хотите избежать нескольких
ssh
подключений, перенаправьте скрипт на другой хост и дайте ему запустить его одной командой:Локальный файл, скажем
myscript.sh
:Затем:
Или (избегая бесполезного использования кошки ):
Это передает локальный сценарий
myscript.sh
на удаленную сторону, где он перенаправляется во (временный) файл/tmp/ms.sh
, выполняется и, наконец, удаляется.Примечание: я не проверял оригинальный скрипт на наличие ошибок, а просто хотел показать идею. Нет необходимости в цитировании, склонном к ошибкам, и все команды в скрипте выполняются на удаленной стороне.
источник
ssh user@host bash <myscript.sh
.mktemp
или что-то подобное, безопасное.Я бы предпочел разместить скрипт на удаленном экземпляре и просто выполнить его через ssh, но вот мое предложение, как это можно сделать так, как вы хотите:
Ноты:
-lt
заменяется на-le
.eval
- построить команду путем объединения аргументов.\"
в$COMMAND{1..3}
выражении, но я решил добавить их.источник