转自:http://www.voidcn.com/article/p-zbofdbwf-rr.html
最近在做pppd程序测试,调用chat脚本的时候需要传递参数,查阅了一下,在这篇文章中找到是用环境变量传递的。
原文:
最近在做pppd程序测试,在修改chat脚本pppd-on-dialer文件时出现了一些小问题,虽然chat脚本似乎并不难懂,但是要精通掌握还是需要花费一点精力的。虽然后来chat脚本问题基本已经解决了,但是为了彻底搞懂chat脚本,在baidu、google能用的关键字都用了结果只有找到一个官方的英文说明,就是没有中文。为了以后参阅花了1个白天3个夜晚的时间将文件翻译成中文。英文水平有限,难免有理解偏差之处,抛砖引玉啦:
CAT中文帮助
名称
chat–调制解调器的自动对话脚本
命令格式
chat [options] script
描述
Chat程序定义了一个计算机和调制解调器之间对话交流,其主要目的是用来在本地PPPD和远端PPPD程序之间建立连接。
选项
-f <chat file>
从chat file文件读取chat脚本。这个选项的使用与chat的脚本参数互斥(mutually exclusive)。 使用者必须具有该文件的读取权限。在文件中允许多线(multiple lines)设定。应该以空格或tab键来分隔字符串。
-l <lock file>
依所指示的锁定文件执行UUCP式的锁定。
如果无法建立该文件那么chat程序将会失败。只有在chat程序因为任何原因而执行失败的情况下该锁定文件才会被删除。 如果该脚本执行成功则锁定文件将会留在磁盘上。当pppd程序不再希望使用串行设备时该锁定文件将会被删除。
不应该同时使用chat以及pppd的锁定选项来使用锁定文件。他们是互斥的选项而且如果你两个都使用将会引起其中一个或者 另一个程序无法获得所需的锁定而失败。
-t <timeout>
对于要接收的预期字符串(expected string)设定的超时限制。如果在该时间限制内没有接收到该字符串的话就不发送回复
字符串(reply string)。可以发送一个变通(alternate)的回复或者如果没有变通的回复字符串则该脚本运行失败。
一个失败的脚本会导致chat程序以一个非零错误代码结束。你也可以使用TIMEOUT字符串来指定超时限制。
-r <report file>
设置报告字符串输出文件。如果你使用REPORT关键字,由此产生的字符串将写入该文件中。 如果没有使用该选项而且你仍使用了REPORT关键字,输出字符串将用标准错误文件记录。
-e
打开echo选项。Echoing使用ECHO关键字在chat脚本的指定位置打开或者关闭。
当echoing被使能,所有调制解调器的输出内容将记录到标准错误文件中。
-E
使能环境变量替换chat脚本中的使用标准的$xxx语法的变量。
-v
要求chat脚本以冗长(verbose)模式执行。
chat程序将记录chat脚本的执行状态,包括所有从调制解调器中接收到的文字以及发送给调制解调器的字符串。
默认记录到SYSLOG去;记录方法可能会通过-S或者-s标志改变。
-V
要求chat脚本使用标准错误的详细模式下执行。 chat程序将记录所有从调制解调器中接收到的文本和发送给调制解调器的字符串到标准错误设备中。 该设备通常是运行chat或pppd程序的本地控制台。
-s
使用标准错误。所有由“-v”产生的日志信息和所有的错误信息将发送到标准错误。
-S
不使用SYSLOG。默认情况下,错误信息被发送到SYSLOG。-S的使用将阻止由’-v’产生的日志信息和错误信息发送到SYSLOG。
-T <phone number>
传递一个任意字符串,通常为一个电话号码,将用于替换发送字符串中的/T替换元字符。
-U <phone number 2>
传递第二个字符串,通常是一个电话号码,将用于替换发送字符串中的/U替换元字符。 当对ISDN终端适配器进行拨号时是非常有用的,它需要两个号码。
script
如果脚本没有以-f选项指定在文件里那么该脚本会如参数般被包含在chat程序里。
CHAT脚本
chat脚本定义通信过程。
一个脚本包含一个或多个“期待对方送出(expect-send)”的配对字符串(pairs of string),
以空格隔开,还有一个选择性的“期待对方送出的候补(subexpect-subsend)”配对字符串,以短线(dash)隔开。像下面这个例子:
ogin:-BREAK-ogin: ppp ssword: hello2u2
这一行指示chat程序应该期待“ogin:”这个字符串。如果在所分配的时间间隔内接收登录提示失败的话,
那它就送出一个中断程序(break sequence)给远端然后期待“ogin:”这个字符串。
如果第一个“ogin:”被接收到那么中断程序就不会产生。
一旦它接收到该登录提示则chat程序将送出ppp这个字符串然后期待“ssword:”这个提示。 当他接收到到密码提示后,他将会送出密码hello2u2。
一般在回复字符串后面会跟着送出一个回车(carriage return)。
在“期待”字符串里除非以/r字符指令(character sequence)指定为必须否则不会期待它的出现。
期待系列(expect sequence)应该只包含辨识字符串所需要的信息。
因为它一般是存放在磁盘文件里,它不应该包含可变信息。
通常不会以时间字符串(time strings),网络识别字符串(network identification strings),或者其他变化的数据做期待字符串。
为了修正在初始化过程中(initial sequence)可能会传送错误的字符,所以寻找字符串“ogin:”而不是“login:”。 开头的“l”字符可能接收错误而你永远找不到该字符串,即使它已经被系统发送。 同样的原因,脚本寻找“ogin:”而不是“login:”以及“ssword:”而不是“password:”。
一个非常简单的脚本看起来可能像这样:
ogin: ppp ssword: hello2u2
换句话说,期待 …ogin:,发送 ppp,期待 …ssword:,再送出hello2u2。
在实际使用上,简单的脚本是罕见的,至少在原先的字符串没有被接收时应该把候补期待(subexpect sequences)包括进来。 例如,考虑下面这个例子:
ogin:--ogin: ppp ssword: hello2u2
这会是个比前面所用的简单脚本跟好的脚本。它会寻找相同的login:提示,然而,
如果没有接收到的话,会发送出一个单独的返回序列(return sequence)并且再次寻找login:。
如果线路干扰掩盖掉第一个login提示那么接着送出空线路(empty line)经常将会再次产生登录提示。
注释
注释可以嵌入在chat脚本中。注释是一个第一列以“#”字符开头的行。注释行仅仅被chat程序忽略。
如果一个“#”出现在期待指令的第一个字母中,你应该引用该字符串。如果你想等待一个以“#”字符开头的提示符,你必须像这样写:
# 现在等待注销的提示和发送字符串
'# ' logout
从文件中发送数据(SENDING DATA FROM A FILE)
如果发送字符串以“@”符号开头,那么该字符串的其余部分被视为一个文件名称用以获取发送字符串。
如果读取文件的最后一个字符是换行字符,它被删除。该文件可以是一个命名管道(或者FIFO)而不是一个普通文件。
这就提供chat和其他程序通信的一个方法,例如,一个程序提供提示用户和接收用户的密码输入。
ABORT字符串
许多调制解调器以字符串来回报呼叫的状态。这个字符串可能是CONNECTED或者是NO CARRIER或者是BUSY。
通常要是调制解调器连接远端失败的话应该会希望结束脚本。困难的是脚本不会确切地知道它可能接收到那个调制解调器字符串。
在初次尝试时,它可能接收到BUSY然而下次它可能接收到NO CARRIER。
这个“失败”字符串可以用ABORT指令指定到脚本中。像下面这个例子一样写到脚本里:
ABORT BUSY ABORT 'NO CARRIER' '' ATZ OK ATDT5551212 CONNECT
这个指令不会期待什么;而且接着发送ATZ这个字符串。对此期待的回应是OK这个字符串。
当它接收到OK时,字符串ADTD5551212就进行拨号。期待字符串是CONNECT。
如果接收到字串CONNECT那么就会执行脚本其余部分。
然而,要是调制解调器发现电话忙线,他将会发送出BUSY这个字符串。
这会使得该字符串符合失败字符命令(abort character)。
这个脚本将会因为它发现一个失败字符串(abort string)而失败(fail)。
如果他接收到的是NO CARRIER字符串,它也会因为同样的原因而失败。
不是可以接收到字符串就是字符串将终结chat脚本。
CLR_ABORT字符串
这个指令允许清除以前的ABORT字符串设置。ABORT字符串被保存在一个预定大小的数组内(在编译时); CLR_ABORT将清除条目的空间回收,以便新的字符串可以使用这些空间。
SAY字符串
SAY指令允许脚本在终端上通过标准错误发送字符串给用户。
如果chat正在被pppd运行,而pppd是作为一个守护进程(同它的控制终端分离)运行,标准错误通常被重定向到文件/etc/ppp/connect-errors中。
SAY字符串必须使用单引号或者双引号。如果字符串中需要输出回车和换行,你必须明确地将它们添加到您的字符串。
SAY字符串可以用来提供那些你使用了“ECHO OFF”但是仍想让用户知道发生什么的脚本段落的进度信息。一个例子是:
ABORT BUSY
ECHO OFF
SAY "Dialling your ISP.../n"
'' ATDT5551212
TIMEOUT 120
SAY "Waiting up to 2 minutes for connection ... "
CONNECT ''
SAY "Connected, now logging in ...0
ogin: account
ssword: pass
$ SAY "Logged in OK ...0 etc ...
这段脚本将目前唯一的SAY字符串发送给用户,所有脚本的详细信息将保持隐藏。例如,如果上面这段脚本运行,用户将看到:
Dialling your ISP...
Waiting up to 2 minutes for connection ... Connected, now logging in ...
Logged in OK ...
REPORT字符串
报告字符串类似于ABORT字符串。所不同的是,字符串和所有字符到下一个控制字符如回车,都被写入报告文件。
报告字符串可以用来分离调制解调器的连接字符串中的发送速率和返回该值给chat用户。 报告字符串的分析产生逻辑结合其他字符串过程像寻找期待字符串。 同样的字符串在报告指令和中止指令中的作用可能不是非常有用,但是,他是可能的。
报告字符串并没有改变程序的完成代码。
这些“报告”字符串被脚本中的REPORT指令所指定。方法如以下示例脚本:
REPORT CONNECT ABORT BUSY '' ATDT5551212 CONNECT '' ogin: account
该脚本不期望什么;接着发送字符串ATDT5551212拨打电话期望的字符串是CONNECT。 如果接收到字符串CONNECT脚本的其余部分将被执行。此外程序将字符串“CONNECT”和跟随它之后的任何字符如连接速率写入预期文件。
CLR_REPORT字符串
这个指令允许清除以前的REPORT字符串设置。REPORT字符串被保存在一个预定大小的数组内(在编译时); CLR_REPORT将清除条目的空间回收,以便新的字符串可以使用这些空间。
ECHO
Echo选项控制是否将调制解调器的输出ECHO到标准错误。该选项可以通过-e选项设置,但它同样可以被ECHO关键字控制。
“期待-发送”对使用ECHO ON使能ECHO,使用ECHO OFF关闭ECHO。使用这个关键字你可以选择哪部分对话应该是可见的。
如下面脚本:
ABORT 'BUSY'
ABORT 'NO CARRIER'
OK/r/nATD1234567
/r/n/c
ECHO ON
CONNECT /c
ogin:account
所有调制解调器的输出结果、配置和拨号是不可见的,但是从CONNECT(或者BUSY)消息之后所有都被echo。
HANGUP
挂断(HANGUP)选项控制调制解调器挂断是否被视作错误。这个选项对拨号系统脚本是非常有用的,挂断并给你系统回电。 HANGUP选项可以是ON或者OFF。
当HANGUP设置为OFF并且调制解调器挂断(例如,登录一个回电系统的第一阶段之后),chat将继续运行脚本(例如,等待一个来电和第二阶段登录提示)。 只要来电被连接,你应该使用HANGUP ON指令重新安装正常挂断信号行为。这里是一个简单的脚本例子:
ABORT 'BUSY'
OK/r/nATD1234567
/r/n/c
CONNECT /c
'Callback login:' call_back_ID
HANGUP OFF
ABORT "Bad Login"
'Callback Password:' Call_back_password
TIMEOUT 120
CONNECT /c
HANGUP ON
ABORT "NO CARRIER"
ogin:--BREAK--ogin: real_account
etc ...
TIMEOUT
初始超时值是45秒。这可以用-t参数来修改。你也可以指定“TIMEOUT 0”。
要对下一个期待字符串改变超时值的话,可以使用下面这个例子:
ATZ OK ATDT5551212 CONNECT TIMEOUT 10 ogin:--ogin: TIMEOUT 5 assword: hello2u2
这将会在在期待“login:”提示的时候把超时限制改成10秒。超时限制接着在它寻找密码提示时被改成5秒。
超时限制一旦改变就会持续作用直到它再度被改变。
传送EOT
EOT这个特别的回复字符串指示chat程序应该发送一个EOT字符到远端去。这是一般的文件结束(End-of-file)字符命令。
在EOT后面并不会跟着发送出去一个返回字符(return character)。这个EOT指令可以用^D指令嵌入到发送的字符串里。
产生中断(GENERATING BREAK)
BREAK这个特殊的回复字符串将会使得一个中断情况被送出。这个中断是发送端的一个特殊信号。
接收端一般对此的处理时改变传输率。它可以用来循环测试远端可能的传输率直到你能够接到有效的登录提示。
这个中断命令可以用/K命令嵌入到发送字符串里。
转义指令(ESCAPE SEQUENCES)
期待以及回复字符串可以包含转义指令。所有这种指令在回复字符串中都是合法的。有许多在期待字符串中是合法的。 那些在期待指令中无效的会被指出。
'' 期待或送出一个空字串(null string)。如果你送出一个空字符串那么它还会送出一个返回字符(/r)。
这个指令可以是一对省略符号(apostrophe)或者也可以是引用字符。
/b代表一个退位(backspace)字符。
/c抑制在回复字符串结尾的新列(newline)字符。这是送出结尾没有返回字符的字符串的唯一方法。 它必须在发送字符串的结尾。例如,这个指令hello/c将会简单地送出字符h,e,l,l,o。(在期待字符串中无效。)
/d 延迟一秒钟。该程序使用最长延迟为一秒的sleep(1)。(在期待字符串中无效。)
/K插入一个中断(在期待字串中无效。)
/n发送一个新列(newline)或换行(linefeed)字元。
/N 送出一个空字符(null character)。同样的指令可以用/0代替。(在期待字符串中无效。)
/p暂停一小段时间。延迟1/10秒。(在期待字符串中无效。)
/q抑制字符串写往SYSLOG文件。该??????字串被记录到自己的空间。(在期待字符串中无效。)
/r传送或期待一个回车字符
/s代替字符串中的空格。这个可以用在不愿引用包含空格的字符串时。HI TIM和HI/sTIM是相同的。
/t传送或期待一个定位(tab)字符。
/T发送-T选项指定的电话号码字符串(在期待中无效)
/U发送-U选项指定的电话号码字符串2(在期待中无效)
// 传送或期待一个反斜线(backslash)字符。
/ddd 将八进制数字(ddd)转换(collapse)成单一的ASCII字符并将其送出。(某些字符在期待字符串中无效。)
^C替换含有以C代表之控制字符的指令。例如,字符DC1(17)是以^Q表示。(某些字符在期待字符串中无效。)
环境变量(ENVIRONMENT VARIABLES)
环境变量在chat脚本中是可用的,如果-E选项在命令行被指定。“$”字符用来引用用来替换的环境变量的。
如果替换失败,那是因为要求的环境变量没有设置,变量不被替换。
结束码(TERMINATION CODES)
chat随着下面的结束码终止运行。
0程序正常终止。这表明脚本没有错误得到正常执行。
1一个或者多个参数是无效字符串或者期待字符串大于内部缓存。这表明该程序没有正确执行。
2一个错误发生在程序执行期间。这可能是由于读或写由于某个原因失败或者chat接收到类似SIGINT的信号量。
3没有被选发送字符串的情况下发生了一个超时事件。这意味着你没有编写正确脚本执行条件或者发生某些突发事件而致期待字符串不能出现。
4第一个字符串标记为ABORT条件发生。
5第二个字符串标记为ABORT条件发生。
6第三个字符串标记为ABORT条件发生。
7第四个字符串标记为ABORT条件发生。
...其他结束码也被认为是一个ABORT条件明显字符串。
使用结束码,有可能确定哪些事件终止了脚本。可以决定是否选择字符串“BUSY”而不是“NO DIAL TONE”。
虽然第一个事件可能会重试,第二个事件在重试过程中成功的机会不大。
参阅(SEE ALSO)
关于chat脚本的其他资料可以在UUCP文件里找到。chat脚本的概念由uucico程序所使用的脚本来的。
uucico(1), uucp(1)
版权(COPYRIGHT)
chat程序是个公益程序(public domain)。这并非是GNU public license。如果它毁掉了你可以保留每块碎片。