Выполнить несколько команд через ssh с локальными и удаленными значениями

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

#!bin/bash

MY_ARRAY=('value1' 'value2' 'value3' 'wrongValue)
for VALUE in "${MY_ARRAY[@]}"
do
    if [[ $VALUE =~ ^v ]] ; then
        echo "$VALUE : $(ssh admin@machine matching_function $VALUE)" >> output.file
    else
        echo "$VALUE : this is a wrong value" >> output.file
    fi
done

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

Я искал способ оптимизировать это и прочитал о передаче многострочных команд в ssh с помощью ssh admin@machine <<EOF и адаптировал свой код:

MY_ARRAY=('value1' 'value2' 'value3' 'wrongValue)
ssh admin@machine << EOF
    for VALUE in "${MY_ARRAY[@]}"
    do
        if [[ $VALUE =~ ^v ]] ; then
            echo "$VALUE : $(matching_function $VALUE)" >> output.file
        else
            echo "$VALUE : this is a wrong value" >> output.file
        fi
    done
EOF

Однако это не работает, и я получаю несколько ошибок:

  • Pseudo-terminal will not be allocated because stdin is not a terminal.. Я подозреваю, что это отчасти связано с тем, что моя удаленная оболочка ограничена и конфликтует с файлом echo.

  • $MY_ARRAY кажется неразмещенным на удаленной машине:

    -rbash: line 5: conditional binary operator expected -rbash: line 5: syntax error near unexpected token '^v' -rbash: line 5: ' if [[ =~ ^v ]] ; then'

Я также не уверен, как bash будет различать $VALUE, который следует интерпретировать с моего локального компьютера, и matching_function, который следует интерпретировать с удаленного компьютера.


person Aserre    schedule 02.05.2014    source источник
comment
Пожалуйста, включите в свой вопрос ваши доказательства того, что это не работает. Есть ли какие-либо сообщения об ошибках, пожалуйста, укажите их тоже. В противном случае вы на правильном пути. Var sub внутри << HEREDOCS является стандартным, в то время как попытка выполнить этот код в локальном пространстве не предпринимается, поэтому ваш macthing_function должен выполняться удаленно.   -  person shellter    schedule 02.05.2014
comment
@shellter Я расширил свой пример, чтобы указать на две разные ошибки, которые я получаю на данный момент.   -  person Aserre    schedule 02.05.2014
comment
сделайте небольшие тесты и убедитесь, что вы понимаете разницу между ssh [email protected] '/bin/ls -l $VAL' и ssh [email protected] "/bin/ls -ls $VAL". Затем добавьте в смесь match_func. Все, что работает внутри "...", будет работать и в <<HEREDOC, если только вы не вызовете жесткие кавычки, такие как <<'HEREDOC', что дает вам то же поведение, что и ..com '/bin/ls -l $VAL'. Удачи.   -  person shellter    schedule 02.05.2014
comment
@shellter спасибо за советы. Я немного поиграл с кавычками ssh, но все же столкнулся с проблемой при выполнении таких вещей, как: ssh x@y "VAL=\$(match_func arg1). Я не могу приписать результат локальной переменной, скорее он создает удаленную переменную и выделяет ей результат функции (я пробовал другие синтаксисы, чтобы попытаться получить этот результат, но безрезультатно)   -  person Aserre    schedule 02.05.2014
comment
Итак, вы получили какие-либо результаты от ssh x@y "VAL=\$(match_func arg1); echo \${VAL}" И, что более важно, и снова возвращаясь к идее маленьких шагов, что происходит, когда вы делаете ssh x@y "match_func StringArg"? Удачи!   -  person shellter    schedule 02.05.2014
comment
@shellter Оба работают. Однако я не могу вернуть возвращенное значение на свой локальный компьютер. Значение существует только на удаленном компьютере   -  person Aserre    schedule 02.05.2014
comment
Перечитывая ваш вопрос и добавив информацию об ошибке, ключевая проблема заключается в том, что MY_ARRAY не расширяется для <<HEREDOC (поскольку сообщение об ошибке показывает, что $VALUE пусто). Опять же, с небольшими тестовыми примерами И с вашей локальной отладкой оболочки, включенной с помощью set -vx, И включенной удаленной отладкой с помощью set -vx; перед любыми командами, отправленными через ssh, вы сможете увидеть, где это терпит неудачу. Это выглядит очень близко, как есть.   -  person shellter    schedule 02.05.2014
comment
НО я могу сказать вам, создавая некоторые довольно сложные функции удаленного доступа по сети для ssh, что время начала работы увеличивается экспоненциально со сложностью кода, который вы пытаетесь отправить по сети. . Отсюда мой рефрен о том, чтобы в первую очередь работать над простыми вещами ;-). Сейчас на работе, наверное, не смогу посмотреть на это до завтрашнего дня. Удачи.   -  person shellter    schedule 02.05.2014


Ответы (2)


man ssh:

Если указано command, оно выполняется на удаленном хосте вместо оболочки входа в систему.

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

ssh admin@machine bash <<EOF
    ...
    #some instructions
    ...
EOF

вместо этого принудительно не запускать оболочку входа.

person Adrian Frühwirth    schedule 02.05.2014

Даже если прошло некоторое время, я отвечу на свой вопрос решением, которое использовал для своей проблемы.

После долгой борьбы с комбинацией heredocs и SSH я нашел частичное решение:

MY_ARRAY=('value1' 'value2' 'value3' 'wrongValue)
ssh admin@machine -T << EOF >output.file
    for VALUE in "${MY_ARRAY[@]}"
    do
        if [[ \$VALUE =~ ^v ]] ; then
            echo "\$VALUE : \$(matching_function \$VALUE)"
        else
            echo "\$VALUE : this is a wrong value"
        fi
    done
EOF

Я использовал $ перед локальными переменными и \$ перед удаленными. Это связано с поведением heredoc, поскольку bash интерпретирует каждую переменную, перед которой стоит $, перед выполнением содержимого heredoc.

>output.file позволил мне перехватить вывод команды ssh и выполнить некоторую постобработку. Тем не менее, я так и не узнал, как выделить переменную из <<EOF ... EOF, но я думаю, что это больше проблема heredoc.

Я приму свой ответ на данный момент, но я буду рад, если кто-нибудь сможет объяснить, почему/если невозможно выделить переменную из heredoc наружу.

person Aserre    schedule 15.05.2014