使用`expect`滚动并接受许可协议。

5

我有一堆刚更新了Xcode的Mac电脑,需要接受最终用户许可协议。我正在尝试通过脚本完成这个过程。

#!/usr/bin/expect
set timeout 15
spawn sudo xcodebuild -license
expect {
    "*License.rtf'\n" {  # Press Enter to view agreement
     send "\r"
    }
    timeout {
        send_user "\nFailed\n";
        exit 1
    }
}
expect {
    "Software License Agreements Press 'space' for more, or 'q' for quit" {
        send_user " ";
        exp_continue;
    }
    "By typing 'agree' you are agreeing" {
        send_user "agree\r"
    }
    timeout {
        send_user "\nTimeout 2\n";
        exit 1
    }
}

然而,它从未通过第一个expect(也就是说,它从未发送“\r”以进行“Enter”)。

以下是输出内容:

$ ./test.sh
spawn sudo xcodebuild -license

You have not agreed to the Xcode license agreements. You must agree to both license agreements     below in order to use Xcode.

Hit the Enter key to view the license agreements at '/Applications/Xcode.app/Contents/Resources/English.lproj/License.rtf'

Failed

编辑:已更新脚本如下,现在在第二个 expect 处超时:

#!/usr/bin/expect
set timeout 15
spawn sudo xcodebuild -license
expect {
    "*License.rtf" {
        send "\r"
    }
    timeout {
        send_user "\nFailed\n";
        exit 1
    }
}
expect {
    "By typing 'agree' you are agreeing" {
        send "agree\r"
    }
    "*Press 'space' for more, or 'q' for quit" {
        send " ";
        exp_continue;
    }
    timeout {
        send_user "\nTimeout 2\n";
        exit 1
    }
}

1
使用 send 而不是 send_user 来发送空格和 "agree" -- 后者会将其发送到终端而不是生成的程序。 - glenn jackman
1
在第二个expect命令之前添加“exp_internal 1”,然后查看哪个模式不匹配。 - glenn jackman
谢谢。那帮了我解决问题。 - Chris
5个回答

9

忽略使用“except”滚动浏览协议的初始主题,但您也可以使用一行代码同意该许可证。

/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -license accept

这对我来说总是有效的。

2

这对我来说是接受Mac OSX Xcode许可证的有效方法。它几乎相同,只需添加bash shell行并确保expect部分的eod标记。我在如何将Expect脚本输出到文件中了解到如何调用expect。

#!/bin/bash
echo "TOP: Now start expecting things"

/usr/bin/expect  -f - <<EOD
set timeout 5
spawn sudo xcodebuild -license
send "\r"
expect {
    "By typing 'agree' you are agreeing" {
        send "agree\r\n"
    }
    "Software License Agreements Press 'space' for more, or 'q' to quit" {
        send " ";
        exp_continue;
    }
    timeout {
        send_user "\nTimeout 2\n";
        exit 1
    }
}
expect {
    timeout {
        send_user "\nFailed\n";
        exit 1
    }
}
EOD

1
这是最终对我有效的脚本。
#!/usr/bin/expect
set timeout 5
spawn sudo xcodebuild -license
send "\r"
expect {
    "By typing 'agree' you are agreeing" {
        send "agree\r\n"
    }
    "Software License Agreements Press 'space' for more, or 'q' to quit" {
        send " ";
        exp_continue;
    }
    timeout {
        send_user "\nTimeout 2\n";
        exit 1
    }
}
expect {
    timeout {
        send_user "\nFailed\n";
        exit 1
    }
}

0

借助@Glenn Jackman提供的信息,我成功解决了这个问题。以下是我的解决方案,嵌入在一个Bash脚本中:

/usr/bin/expect<<EOF
spawn sudo xcodebuild -license              
expect {
    "*License.rtf" {
        send "\r";
    }
    timeout {
        send_user "\nExpect failed first expect\n";
        exit 1; 
    }
}
expect {
    "*By typing 'agree' you are agreeing" {
        send "agree\r"; 
        send_error "\nUser agreed to EULA\n";
     }
     "*Press 'space' for more, or 'q' to quit*" {
         send "q";
         exp_continue;
     }
     timeout {
         send_error "\nExpect failed second expect\n";
         exit 1;
     }
}
EOF

0

为了后人,因为这个问题仍未得到解答

最终我使用了以下方法,对我来说可行(但可能不是最干净的方法):

!/usr/bin/expect
set timeout 5
spawn sudo xcodebuild -license
expect {
    "By typing 'agree' you are agreeing" {
        send "agree\r\n"
    }
    "Software License Agreements Press 'space' for more, or 'q' to quit" {
        send " ";
        exp_continue;
    }
    timeout {
        send_user "\nTimeout 2\n";
        exit 1
    }
}
expect {
    timeout {
        send_user "\nFailed\n";
        exit 1
    }
}

我是如何得出这个结论的:

我通过在顶部调用expect -d进行调试,如下所示:

!/usr/bin/expect -d

一旦我知道它寻找的是“agree”,而不是“space”,我就改变了顺序并删除了“-d”。

这是我的第一次尝试expect,如果有其他建议,我会感到非常高兴,并且我对这个工具印象深刻!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接