嵌入式工作中总会有各种需求,比如这次,客户希望在板子上实现scp免确认,直接传送文件。那是经过一番折腾,可算是实现了,前因后果,且看下面慢慢道来。
scp 工作模式 ,当用scp 传送文件时,首次总会让确认
$ scp vimrc [email protected]:~
The authenticity of host '192.168.9.250 (192.168.9.250)' can't be established.
ECDSA key fingerprint is SHA256:SXkTDqjo+6RFecNQPGw4DxgX9lz8qmphja4HbHR8rL8.
Are you sure you want to continue connecting (yes/no)?
其大概意思就是,要传送的目的ip(此处的192.168.9.250)不是本机 ~/.ssh/known_hosts 里面,~/.ssh/known_hosts 其实是一张表,记录这所有可以直接scp的host ip。
要避免确认的方法有很多, 比如更改ssh的配置文件、第一次确认后即可等。但是有这样一个应用场景,嵌入式板子中没有ssh的配置文件,如这里用的自研imx6q平台,但是客户有希望开机启动时进行文件同步,完全不给输入 yes的机会。哦豁~ 这个咋个整嘛~,客户又得罪不起多。
哈哈,经过一番查找,不得不说,很感谢度娘的强大和技友(技术朋友)们的热心,有人说可以通过 expect 自动和终端进行交互实现,那咱们也试试。经过大半天的尝试,完成如下脚本,名之曰为 auto_scp:
#!/usr/bin/expect
spawn scp test.txt [email protected]:~
expect {
"y/n" {exp_send "y\r"; interact}
}
在终端下通过命令 $ expect auto_scp ,即可成功自动传送文件到目标机上。这里需要说明的一点是,pc 上使用scp和嵌入式平台使用scp 提示信息可能有出入,所以 expect匹配也是不一样的。如这里 匹配 "y/n"是imx6q平台上的;而在pc上验证的时候匹配的是"yes/no"。
auto_scp 脚本大概表述是, 先执行一个scp的动作,通过spawn 关键字执行。expect { } 里进行匹配和执行相关的操作,双引号表示匹配的内容,匹配成功后执行后面的 exp_send 操作,发送一个字符'y'并回车。然后继续执行 interact,即把执行权交还终端。
那么问题又来了,嵌入式平台没有expect命令。移植呗,有源码还不能搞点事情阿 ^_^ . 这里需要两个部分的源码交叉编译,tcl 和 expect。why? because expect depend on tcl 啊~
tcl移植思路:拉源码-》配置编译(中间省略N个步骤 🙈),直接上步骤
wget http://prdownloads.sourceforge.net/tcl/tcl8.4.20-src.tar.gz # get source codes
tar xvf tcl8.6.20-src.tar.gz # unzip
cd tcl8.6.20/
cd unix/ # path to work
export tcl_cv_type_64bit="long long"
export ac_cv_c_bigendian=no
export tcl_cv_strtod_buggy=1
export ac_cv_func_strstr=yes
export ac_cv_func_opendir=yes # export necessary environment variable
./configure --prefix=/usr/lib --host=arm-linux # configure
#export toolchain
source /opt/fslc-framebuffer/2.5/environment-setup-armv7at2hf-neon-fslc-linux-gnueabi
make V=s
make install
这里有一个小经验分享一下,最好将安装路径配置为 "/usr/lib" ,因为在嵌入式平台执行expect时,会根据安装路径去找init.tcl,一定会根据 安装路径去找的!安装不一定会成功,也可以不安装,毕竟编译成功就会成功了90%了。
expect编译
expect
wget http://sourceforge.net/projects/expect/files/Expect/5.45/expect5.45.tar.gz
./configure --prefix=expect_install --with-tcl=xxxx/tcl_install/lib --with-tclinclude=xxx/tcl_install/include --host=x64
expect 配置需要指定tcl的头文件和库,然后指定host为x86的, 因为expect 不支持交叉编译,据说有patch,无奈时间不等人,先产生makefile然后再改吧,这也是曲线救国阿。修改makefile中的 CC 和AR,编译即可生成所需的expect和库。部署到板子上,大功告成!