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.
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