昔我往矣

Expect中被忽视的超时

2016年05月2日

以前写过一个expect脚本,用于每天凌晨登录远端sftp服务器同步文件,但是偶尔会发现登录失败,查不出来原因,所以设置了每天同步两次,可惜依然有时候失败。直到我发现了expect的超时设置,据说expect默认超时时间是10s。

为了证实这个问题,我写了简易的脚本做验证,把登录sftp换成了http服务,道理是一样的。下面是在没有给expect设置超时的情况,我写了个flask服务,用来做测试,demo.py。

简单的http服务

#!/usr/bin/python

import flask
import time

app = flask.Flask(__name__)

@app.route("/sleep")
def justsleep():
    time.sleep(15)
    return "awake\n"

if __name__ == '__main__':
    app.run()

服务路径是http://localhohst:5000/sleep,作用是在休息15s之后,给客户端返回awake的字符串。

没有timeout设置的expect

下面是我的expect脚本,http_client.exp

#!/usr/bin/expect -f

spawn /usr/bin/curl -s http://127.0.0.1:5000/sleep
expect

这个脚本的用途是去curl http://127.0.0.1:5000/sleep 服务,等待命令结束。

运行服务和脚本试试,先启动服务:

$ python demp.py

然后运行exp脚本:

$ /usr/bin/expect ./http_client.exp
spawn /usr/bin/curl -s http://127.0.0.1:5000/sleep

等等,过了10s之后,脚本没等到服务返回的awake字样就退出了。而且flask有报错

Exception happened during processing of request
...

也就是说,http_client.exp正在运行着,然后就突然退出了。这个就是就是在expect里不设置超时导致的问题,expect默认超时时间为10s,如果10s中还没有返回,就会退出脚本。

解决超时问题

修改http_client.exp文件,如下

#!/usr/bin/expect -f

set timeout 20

spawn /usr/bin/curl -s http://127.0.0.1:5000/sleep
expect

这次添加了一行set timeout 20,也就是设置20s的超时时间。再次运行http_client.exp脚本,等待15s,终于看到了awake。

$ ./http_client.exp
spawn /usr/bin/curl -s http://127.0.0.1:5000/sleep
awake

所以,这里的timeout指定了最长的等待时间。

最后

所以回到我遇到的问题上,就是sftp脚本要去同步远程服务器上,由于中间的网络很慢,而expect默认超时时间是10s,如果10s中还未能登录成功,自然就无法同步远程sftp服务器的文件。

如果不想不能确定要设置多长的超时时间,可以尝试set timeout -1,也就是永不超时。祝你玩得愉快。

当前暂无评论 »

添加新评论 »