spawn - 未找到命令!

dev*_*v2d 17 bash shell-script expect

我使用的是 Mac OS X 10.9.4,以下是我将文件从本地机器复制到不同主机的脚本

#!/bin/bash
#!/usr/bin/expect

echo "I will fail if you give junk values!!"
echo " "
echo "Enter file name: "
read filePath
echo " "
echo "Where you want to copy?"
echo "Enter"
echo "1. if Host1"
echo "2. if Host2"
echo "3. if Host3"
read choice
echo " "
if [ $choice -eq "1" ]
then
  spawn scp filePath uname@host1:/usr/tmp   
  expect "password"   
  send "MyPassword\r"
  interact
elif [ $choice -eq "2" ]
then
  spawn scp filePath uname@host2:/usr/tmp   
  expect "password"   
  send "MyPassword\r"
  interact
elif [ $choice -eq "3" ]
then
  spawn scp filePath uname@host3:/usr/tmp   
  expect "password"   
  send "MyPassword\r"
  interact
else
  echo "Wrong input"
fi
Run Code Online (Sandbox Code Playgroud)

运行此脚本时,我正在关注

./rcopy.sh: line 21: spawn: command not found
couldn't read file "password": no such file or directory
./rcopy.sh: line 23: send: command not found
./rcopy.sh: line 24: interact: command not found
Run Code Online (Sandbox Code Playgroud)

ter*_*don 22

您的脚本正在尝试组合两个解释器。你有#!/bin/bash#!/usr/bin/expect。那行不通。您只能使用两者之一。从bash第一次开始,您的脚本就作为 bash 脚本运行。

但是,在您的脚本中,您有expect诸如spawn和 之类的命令send。由于脚本正在被读取bash而不是被读取expect,因此失败。您可以通过编写不同的expect脚本并从您的bash脚本中调用它们或将整个内容转换为expect.

不过,最好的方法,也是避免将密码以纯文本格式保存在简单文本文件中这种可怕做法的方法,是改为设置无密码 ssh。这样,scp就不需要密码,您也不需要expect

  1. 首先,在您的机器上创建一个公共 ssh 密钥:

    ssh-keygen -t rsa
    
    Run Code Online (Sandbox Code Playgroud)

    系统会要求您输入密码,每次登录后第一次运行任何 ssh 命令时都会要求您输入该密码。这意味着对于多个 ssh 或 scp 命令,您只需输入一次。将密码短语留空以实现完全无密码访问。

  2. 生成公钥后,将其复制到网络中的每台计算机:

    while read ip; do 
     ssh-copy-id -i ~/.ssh/id_rsa.pub user1@$ip 
    done < IPlistfile.txt
    
    Run Code Online (Sandbox Code Playgroud)

    IPlistfile.txt应该是包含在每一行的服务器的名称或IP的文件。例如:

    host1
    host2
    host3
    
    Run Code Online (Sandbox Code Playgroud)

    由于这是您第一次执行此操作,您必须手动输入每个 IP 的密码,但是一旦完成,您就可以使用简单的方法将文件复制到这些机器中的任何一台:

    scp file user@host1:/path/to/file
    
    Run Code Online (Sandbox Code Playgroud)
  3. 从您的脚本中删除期望。现在您拥有无密码访问权限,您可以将脚本用作:

    #!/bin/bash
    echo "I will fail if you give junk values!!"
    echo " "
    echo "Enter file name: "
    read filePath
    echo " "
    echo "Where you want to copy?"
    echo "Enter"
    echo "1. if Host1"
    echo "2. if Host2"
    echo "3. if Host3"
    read choice
    echo " "
    if [ $choice -eq "1" ]
    then
      scp filePath uname@host1:/usr/tmp   
    elif [ $choice -eq "2" ]
    then
      scp filePath uname@host2:/usr/tmp   
    elif [ $choice -eq "3" ]
    then
      scp filePath uname@host3:/usr/tmp   
    else
      echo "Wrong input"
    fi
    
    Run Code Online (Sandbox Code Playgroud)


gle*_*man 5

您的代码可以更加简洁:

#!/bin/bash

read -p "Enter file name: " filePath
if ! [[ -r $filePath ]]; then
    echo "cannot read $filePath"
    exit 1
fi

PS3="Where you want to copy? "
select host in host1 host2 host3; do
    if [[ -n $host ]]; then
        expect <<END
            spawn scp "$filePath" uname@$host:/usr/tmp   
            expect "password"   
            send "MyPassword\r"
            expect eof
END
        break
    fi
done
Run Code Online (Sandbox Code Playgroud)

如果您按照建议设置 ssh 密钥,那就更好了:

    if [[ -n $host ]]; then
        scp "$filePath" uname@$host:/usr/tmp   
        break
    fi
Run Code Online (Sandbox Code Playgroud)