ssh - выполнить сложную удаленную команду

Вы можете сделать что-то вроде следующего в bash, zsh или ksh:

SECONDS=0
while   command
do      sleep "$((10-(SECONDS%10)))"
done

Вот что говорится в руководстве bash о $SECONDS:

$SECONDS

  • При каждом обращении к этому параметру возвращается количество секунд с момента вызова оболочки. Если параметру $SECONDS присвоено значение, то при последующих обращениях возвращается количество секунд с момента присвоения плюс присвоенное значение. Если $SECONDS будет сброшен, он потеряет свои специальные свойства, даже если впоследствии будет сброшен.

Вот рабочий пример:

(   SECONDS=0
    while   sleep   "$((RANDOM%10))"
    do      sleep   "$((10-(SECONDS%10)))"
            echo    "$SECONDS"
    done
)

10
20
30
40
50
60
70
80
90
100
0
16.03.2018, 15:23
2 ответа

Ваша работа была бы намного проще, если бы вы просто создали сценарий в другой системе, который делал то, что вы хотели, а затем вызвали этот сценарий без каких-либо параметров. Альтернативой является создание сценария на другой стороне, который показывает, какие параметры он получает, что-то вроде echo _args.sh:

#!/bin/ksh

echo "$0 $@"
ARG=1
while [ $# -gt 0 ]
do
  echo "$ARG: $1"
  shift
  (( ARG++ ))
done

Тогда вы можете позвонить:

ssh tomcat@rmgdmzwebapp02.dmz.local bin/echo_args.sh  -f -u \'INFORMATION \\[main\\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \\[\\\"ajp-nio-8009\\\"\\]\' /opt/tomcat/logs/catalina.out

и вы получите:

bin/echo_args.sh -f -u INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\] /opt/tomcat/logs/catalina.out
1: -f
2: -u
3: INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]
4: /opt/tomcat/logs/catalina.out

, который показывает, что параметры правильно поступают на другую сторону. Теперь вы просто заменяете echo _args.sh своей розничной программой:

ssh sshuser@my-server.net.bar /bin/retail -f -u \'INFORMATION \\[main\\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \\[\\\"ajp-nio-8009\\\"\\]\' /opt/tomcat/logs/catalina.out
1
28.01.2020, 02:15

Рекомендация Jaken551 близка к фактическому решению, но немного отличается из-за дополнительного уровня вложенной цитаты. Давайте сначала посмотрим, что происходит с этим.

Моя обычная техника для этого состоит в том, чтобы просто поставить echoперед командой (это не идеально, но обычно достаточно хорошо ).

# Your original command which you say works locally
$ echo 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out
INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\] /opt/tomcat/logs/catalina.out

# The command though ssh
$ ssh example.com echo "INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]" /opt/tomcat/logs/catalina.out
INFORMATION [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler [ajp-nio-8009] /opt/tomcat/logs/catalina.out

# The command through ssh with the quotes
$ ssh example.com 'echo "INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]" /opt/tomcat/logs/catalina.out'
INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \["ajp-nio-8009"\] /opt/tomcat/logs/catalina.out

Итак, обратите внимание на разницу в результатах. В обеих версиях sshэкранирование отличается.

Что происходит в первом sshпримере, так это то, что первый уровень цитаты удаляется локальной оболочкой, затем sshполучает несколько аргументов (echo, INFORMATION \[main\]...), которые затем объединяются вместе в один аргумент echo INFORMATION \[main\]..., который затем оценивается через оболочку на удаленной стороне как sh -c 'echo INFORMATION \[main\]...'.

Во втором примере sshпервый уровень цитирования снова удаляется локальной оболочкой, поэтому ssh получает echo "INFORMATION \[main\]...", который затем оценивается на удаленной стороне как sh -c 'echo "INFORMATION \[main\]..."'. Так что это немного лучше, но вы все еще имеете дело с двумя уровнями оболочек, удаляющих ваши цитаты и экраны.

 

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

.
ssh -T example.com <<'EOF'
echo 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out
EOF
INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\] /opt/tomcat/logs/catalina.out

Однако это означает, что удаленная команда не имеет доступа к вашему TTY или STDIN, поэтому, если команде требуется STDIN, она не будет работать.

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

$ CMD="$(printf "%q " echo 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out)"
$ ssh example.com "$CMD"
INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\] /opt/tomcat/logs/catalina.out

(вам не нужен посредник $CMD, и вы можете сделать встроенный ssh... "$(printf "%q "...)",Я просто сделал это отдельно для разборчивости)

 

TL;DR :Любой из следующих вариантов вам подойдет:

ssh -T sshuser@my-server.net.bar <<'EOF'
/bin/retail -f -u 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out
EOF

CMD="$(printf "%q " /bin/retail -f -u 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out)"
ssh sshuser@my-server.net.bar "$CMD"
2
28.01.2020, 02:15

Теги

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