Question

I am writing a script to match local values with remote ones. As of now, my code is functional and looks like this :

#!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

The only problem is that for every iteration of the loop, it creates and closes a new ssh connection. As my original dataset is quite big, it takes a long time to execute.

I was looking for a way to optimize this, and read about passing multiline commands to ssh with ssh admin@machine <<EOF and adapted my code:

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

However, it does not work and I get several errors :

  • Pseudo-terminal will not be allocated because stdin is not a terminal.. I suspect this is partly due to the fact my remote shell is restricted, and it conflicts with the echo.

  • $MY_ARRAY seems to be unalocated on remote machine :

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

I am also unsure about how bash will differentiate $VALUE, which should be interpretated from my local computer, and matching_function, which should be interpretated from the remote one

Was it helpful?

Solution 2

Even if it's been some time, I'll answer my question with the solution I used for my problem.

After struggling a LOT with the combination of heredocs and SSH, I came up with a partial solution :

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

I used $ before local variables, and \$ before remote ones. This is due to heredoc behaviour, as bash interpretes every varaible preceeded by a $ before executing the content of the heredoc.

The >output.file allowed me to catch the output of the ssh command and do some postprocessing. However, I never found out how to allocate a variable out of the <<EOF ... EOF, but I guess this is more of a heredoc issue.

I'll accept my answer as of now, but I'll be glad if anyone could clarify why/if it is impossible to allocate a variable from the heredoc to the outside.

OTHER TIPS

man ssh:

If command is specified, it is executed on the remote host instead of a login shell.

People might tell you that you can force allocating a pseudo-tty by using various amounts of -t which does work but comes with the side effect of running a login shell, therefore it might be better to just do

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

instead to force not executing a login shell.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top