最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin0浏览0评论

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

Share Improve this question edited Feb 4 at 18:41 Enub asked Jan 31 at 21:43 EnubEnub 12 bronze badges 2
  • I removedosascript tag and added expect tag as it seems to be an expect issue for Glenn... – Mark Setchell Commented Jan 31 at 22:34
  • 4 All this nested quoting is nearly impossible to get right. Instead of trying to put everything in a single string, it would be better to write the expect script in its own file, and pass it the host and password as command-line arguments. – Barmar Commented Jan 31 at 22:34
Add a comment  | 

1 Answer 1

Reset to default 0

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
发布评论

评论列表(0)

  1. 暂无评论