天天看点

shell实现SSH自动登陆 shell脚本基础 expect解释器完成脚本alias别名总结

前些天在同事进行技术分享时,看到他竟然只输入了一行命令<code>./test.sh</code>就成功登陆了开发机,甚是惊异,于是回来搜索研究了一下,遂成此文。

在编写ssh自动登陆脚本之前,先说一下shell脚本的基础,此基础不是一些语法什么的,网上到处都是,这里总结了一下shell脚本的运行机制~

首先要说一下shell的几种启动方式,正是踩了脚本启动的坑,才使用原来十分钟就搞定的脚本,花了两个小时才搞定。同时也使得我们运行shell,知其所以然。

shell脚本可以直接通过文件名执行,需要注意的是文件需要执行权限。通过 <code>sudo chmod +x ./file_name.sh</code> 来给文件添加执行权限;

我们常用的 <code>sh file_name.sh</code> 就是指定了脚本解释器 <code>/bin/sh</code>来解释执行脚本;常见的脚本解释器还有:<code>/bin/bash</code>等,我们可以使用<code>ls -l /bin/*sh</code>命令来查看当前可用的脚本解释器;

这种方式不会像前两种方式一样fork一个子进程去执行脚本,而是使用当前shell环境执行,用于 .bashrc或者.bash_profile被修改的时候,我们不必重启shell或者重新登录系统,就能使当前的更改生效。

我们写一个shell脚本时,总是习惯在最前面加上一行 <code>#!/binbash</code>,它就是脚本的<code>shebang</code>,至于为什么叫这么个奇怪的名字,C语言和Unix的开发者丹尼斯·里奇称它为<code>可能是类似于"hash-bang"的英国风描述性文字</code>;

贴一段wiki上的解释:

在计算机科学中,Shebang是一个由井号和叹号构成的字符串行,其出现在文本文件的第一行的前两个字符。 在文件中存在Shebang的情况下,类Unix操作系统的程序载入器会分析Shebang后的内容,将这些内容作为解释器指令,并调用该指令,并将载有Shebang的文件路径作为该解释器的参数。

简单的说,它指示了此脚本运行时的解释器,所以,使用文件名直接执行shell脚本时,必须带上shebang; 此外,我们还可以在shebang后面直接附加选项,执行时我们默认使用选项执行;

如 <code>test.sh</code>的<code>shebang</code>为 <code>#!/bin/sh -x</code>,那我们执行脚本时:

<code>./test.sh hello</code>

相当于:

<code>bin/sh -x ./test.sh hello</code>;

而编写一个ssh自动登陆脚本,需要用到的shebang(解释器)为 <code>/usr/bin/expect</code>;

需要注意的是:在指定脚本解释器来执行脚本时,shebang会被指定的脚本解释器覆盖,即优先使用指定的脚本解释器来执行脚本(习惯性地用sh ./test.sh却提示command not found)

expect是一个能实现自动和交互式任务的解释器,它也能解释常见的shell语法命令,其特色在以下几个命令:

<code>spawn command</code>命令会fork一个子进程去执行command命令,然后在此子进程中执行后面的命令;

在ssh自动登陆脚本中,我们使用 <code>spawn ssh user_name@ip_str</code>,fork一个子进程执行ssh登陆命令;

expect命令是expect解释器的关键命令,它的一般用法为 <code>expect "string"</code>,即期望获取到string字符串,可在在string字符串里使用 * 等通配符;

string与命令行返回的信息匹配后,expect会立刻向下执行脚本;

<code>set timeout n</code>命令将expect命令的等待超时时间设置为n秒,在n秒内还没有获取到其期待的命令,expect 为false,脚本会继续向下执行;

send命令的一般用法为 <code>send "string"</code>,它们会我们平常输入命令一样向命令行输入一条信息,当然不要忘了在<code>string</code>后面添加上 <code>\r</code> 表示输入回车;

interact命令很简单,执行到此命令时,脚本fork的子进程会将操作权交给用户,允许用户与当前shell进行交互;

以下是一个完成版的脚本 <code>test.sh</code>:

执行 <code>sudo chmod +x ./test.sh</code>命令给shell脚本添加执行权限;

运行 <code>./test.sh</code>命令,一键登陆成功!

简单的几个命令,,搭配起来解决了与命令行的交互问题后,很多复杂的功能也不在话下了~

脚本完成了,可是还是有些小瑕疵:

输入<code>./file_name.sh</code>命令太长。。。

只能在脚本目录中才能执行,不然使用绝对路径输出的命令更长。

这里我们想到了linux的alias命令:

alias命令使用方式为 <code>alias alias_name="ori_command"</code>,将alias_name设置为ori_command的别名,这样我们输入执行alias_name,就相当于执行了ori_command;

可是,我们会发现,当你关闭当前shell后,再打开一个shell窗口,再使用alias_name,系统提示<code>command not found</code>;

有没有能保持命令的方式呢?编辑bash_profile文件。

我们编辑bash_profile文件,此文件会在终端窗口创建的时候首先执行一次,所以可以帮我们再设置一次别名;

执行命令<code>vim ~./bash_profile</code>,在文件内部添加:

<code>alias alias_name="/root_dir/../file_name.sh</code>

保存后,再使用 <code>. ~./bash_profile</code>或<code>source ~./bash_profile</code> 在当前脚本执行一遍设置别名命令,完成设置;

这样,我们无论在哪个目录,只要输入<code>alias_name</code>命令,回车,真正的一键登陆!

作为一个程序猿,时刻保持着<code>偷懒</code>意识(当然此偷懒非彼偷懒。。。),在类unix系统中,不要浪费了<code>shell</code>这种神奇的工具,让计算机为我们服务~

一个多月没写博客了,最近在看APUE,UNP一套的书,C和Unix上入门尚浅,不敢乱写误人子弟;平常自己用记事本做的笔记也比较散乱,不成系统;

 转自:http://www.cnblogs.com/zhenbianshu/p/5867440.html 

心得:看到此文,亲身实践,顿觉收获颇丰,遂转载作为笔记!程序员就是要越简洁越好,提升效率! 

若转载请注明出处!若有疑问,请回复交流!