Search code examples
bashmacosexpectgnome-terminal

How can I remotely assign a variable in gnome-terminal via a bash script?


I am running the following script in a bash terminal on a mac:

#!/bin/bash

string_list=(
    host1
    host2
    host3
    host4
    ) 

password="12345"

for i in "${!string_list[@]}"; do
    host="${string_list[$i]}"
    
    osascript -e "
    tell application \"Terminal\"
        do script \"expect -c '
        spawn ssh -L 9999:localhost:9999 $host
        expect \\\"password:\\\"
        send \\\"$password\\r\\\"
        expect \\\"\$\\\"
        send \\\"foldername=\$(find 25* 2>/dev/null | grep -E '^25' | grep -v 'cycle' | sort | tail -n 1 | sed 's/.$//')\\r\\\"
        expect \\\"\$\\\"
        send \\\"cd \$foldername/\${foldername}_01/logs && tail -f console.log\\r\\\"
        interact'\"
    end tell"
done

It works well until the command that assigns the value of foldername. I get the error:

can't read "(find 25* 2>/dev/null | grep -E ^25 | grep -v cycle | sort | tail -n 1 | sed s/.$//)": no such variable
    while executing
"send "foldername=$(find 25* 2>/dev/null | grep -E ^25 | grep -v cycle | sort | tail -n 1 | sed s/.$//)
""

When I am remoted into the gnome terminal without using this script, I can run

foldername=$(find 25* 2>/dev/null | grep -E '^25' | grep -v 'cycle' | sort | tail -n 1 | sed 's/.$//')

which works perfectly. The issue to me seems like the apostrophes are not being interpreted properly in the expect command. I have tried escaping them but nothing seems to work. Using double quotes instead of apostrophes leads to invalid syntax. I have tried the solution from this post using

send -- \\\"foldername=$(find 25* 2>/dev/null | grep -E '^25' | grep -v 'cycle' | sort | tail -n 1 | sed 's/.$//')\r\\\"

but that leads to another issue where the command runs, but just appears as foldername= in the terminal, so the variable is not assigned properly and the cd command fails. I've also tried various alterations with the help of shellcheck.net to no avail.

Is there a way to fix this command so it works as intended? Or to use a different set of commands to achieve the same result? For clarity, I am trying to open a terminal for each host, remote in, find the folder in the directory that starts with 25, does not contain the word cycle, and has the lexicographically largest value, navigate to it, and tail the log file.

I know plaintext passwords are generally not good practice. It doesn't matter for this application.


Solution

  • I found a work-around. The issue is that in both bash script and gnome terminal, $ is used to access a variable, and when using it in expect/send the script can't differentiate, so it will try to use a variable that is undeclared inside the bash script, rather than accessing a variable stored locally in the gnome terminal.

    Instead, I've opted to just use another do script after a delay. Here is the final script:

    #!/bin/bash
    
    host_list=(
        "host1"
        "host2"
        "host3"
        ) 
    
    password="12345"
    
    for i in "${!host_list[@]}"; do
        host="${host_list[$i]}"
    
        osascript -e "
        tell application \"Terminal\"
            do script \"expect -c '
            spawn ssh -L 9999:localhost:9999 $host
            expect \\\"password:\\\"
            send \\\"$password\\r\\\"
            expect \\\"$\\\"
            interact'\"
    
            delay 1
            do script \"filename=\$(ls 25* 2>/dev/null | grep -E '^25' | grep -v 'cycle' | sort | tail -n 1 | sed 's/.$//');echo \$filename;cd \$filename/\${filename}_01/logs;tail -f console.log\" in front window
        end tell"
    done