Как SSH может работать с если условие?

Я имею 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: Никакой такой файл или каталог

8
задан 3 December 2018 в 03:02

4 ответа

Примечание: существует на самом деле два слоя к вопросу здесь. Каждый, 'Я хочу выполнить нетривиальную задачу на удаленном сервере, доступном через SSH'. Другой, 'я пытаюсь передать сложную строку команде, и аргумент заканчивает тем, что отличался от того, что я предназначил'. Я отвечаю на вопрос низкого уровня, не обсуждая, является ли используемый подход "правильным" (удобный, неподверженный ошибкам, безопасный и т.д.) для решения высокого уровня один. Как обозначено другими ответами и комментариями, это вполне возможно не.

Ваша командная строка является главным образом правильной; только необходимо изменить заключение в кавычки немного.

Основная проблема состоит в том, что дважды заключенные в кавычки строки расширены Вашей локальной оболочкой, и таким образом, $(...) части будут оценены в Вашей локальной системе. Для передавания их к удаленной системе необходимо включить сценарий в одинарные кавычки.

У Вас также есть некоторые встроенные кавычки. В Вашем исходном сценарии существуют аргументы в пользу двух echos; при изменении внешней цитаты на одинарные кавычки это будет awk сценарий. Эти effecitvely приводят к опускаемым кавычкам, который не беспокоится echos, но это испортит awk сценарий как большее - чем знак станет перенаправлением вывода. Таким образом после того, как Вы изменяете внешние кавычки на одинарные кавычки, изменяете кавычки к двойным кавычкам.

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

#!/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'
3
ответ дан 23 November 2019 в 05:23

Да Вы можете exexute сложные сценарии через ssh

#!/bin/bash -e

ssh_cmd="$(cat <<-EOF
    cd /var/www/test.com/backup;

    if [ \$(ls  | wc -l) -lt 3  ]; then
        echo "less"
    elif [ \$(ls -t *.tgz|awk 'NR >3'|xargs rm -f) ]; then
        echo "deleted"
    else
        echo "something else"
    fi
EOF
)"

ssh -t test@192.168.94.139 "$ssh_cmd"

Этот пример использует удар здесь документ для генерации командной строки. В любом случае, передающие сценарии через ssh подвержено ошибкам, потому что заключение в кавычки и выход переменных являются трудными (возражайте против обратной косой черты перед командами). Если сценарий становится слишком сложным, лучше скопировать его через scp и затем выполните его на целевом узле.

Я не пытался исправить Ваш сценарий, но здесь являюсь примером о том, как подсчет и удаление на удаленном хосте могли работать:

#!/bin/bash -e

tmp_dir="$(mktemp -d)"

ssh_cmd="$(cat <<-EOF
    cd "$tmp_dir"

    cnt_tgz=(\$(find . -type f -name "*.tgz"))
    if [[ \${#cnt_tgz[@]} -lt 3 ]]; then
        echo "less"
    else
        rm "\${cnt_tgz[@]}"
        echo "deleted"
    fi
EOF
)"

touch "$tmp_dir/1.tgz"
ssh -t localhost "$ssh_cmd"
touch "$tmp_dir/2.tgz" "$tmp_dir/3.tgz"
ssh -t localhost "$ssh_cmd"

ls -t *.tgz не будет работать, так как globbing только происходит в локальной системе. Также использование ls для подсчета файлов не хорошая идея, так как он также возвращает записи как ., .. и каталоги.

10
ответ дан 23 November 2019 в 05:23

Я думаю, что этот целый сложный материал заключения в кавычки является доказательством достаточно, чтобы не использовать его, но использовать сценарий вместо этого. Если Вы хотите избежать нескольких ssh соединения, передайте сценарий по каналу к другому хосту и позвольте ему работать туда в одной команде:

Локальный файл, говорят myscript.sh:

cd /var/www/test.com/backup;

if [ $(ls  | wc -l) -lt 3  ]; then
    echo "less"
elif [ $(ls -t *.tgz|awk 'NR >3'|xargs rm -f) ]; then
    echo "deleted"
else
    echo "something else"
fi

Затем:

cat myscript.sh | \
    ssh -t test@192.168.94.139 \
    "cat - > /tmp/ms.sh && sh /tmp/ms.sh && rm /tmp/ms.sh"

Или (предотвращение бесполезного использования кошки):

ssh -t test@192.168.94.139 \
    "cat - > /tmp/ms.sh && sh /tmp/ms.sh && rm /tmp/ms.sh" \
    < myscript.sh

Это передает локальный сценарий по каналу myscript.sh удаленной стороне, где это перенаправляется во (временный) файл /tmp/ms.sh, выполняемый, и наконец удаленный.

Примечание: Я не проверял исходный сценарий на наличие ошибок, но просто требуемый для показа идеи. Никакое подверженное ошибкам заключение в кавычки не необходимо, и все команды в сценарии выполняются на удаленной стороне.

4
ответ дан 23 November 2019 в 05:23

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

#!/bin/bash

HOST='test@192.168.94.139'
REMOTE_PATH='/var/www/test.com/backup'

COMMAND1="ssh \"$HOST\" 'ls \"$REMOTE_PATH\" | wc -l'"
COMMAND2="ssh \"$HOST\" 'ls -t \"$REMOTE_PATH\"/*.tgz'"
COMMAND3="xargs ssh \"$HOST\" rm -rf"

if [[ $(eval "$COMMAND1") -le 3 ]]
then
    echo "Less"
else
    eval "$COMMAND2" | awk 'NR > 3' | eval "$COMMAND3" && echo "Deleted"
fi

Примечания:

  • Условное выражение -lt заменяется -le.
  • eval - создайте команду путем конкатенации аргументов.
  • Я не уверен, делают нам действительно нужны эти дополнительные цитаты \" в $COMMAND{1..3} выражение, но я решаю добавить их.
3
ответ дан 23 November 2019 в 05:23

Другие вопросы по тегам:

Похожие вопросы: