2005年09月03日


PPID : 该bash的呼叫者process ID.
PWD : 目前的工作目录。
OLDPWD : 上一个工作目录。
REPLY : 当read命令没有参数时,直接设在REPLY上。
UID : User ID。
EUID : Effective User ID。
BASH : Bash的完整路径。
BASH_VERSION : Bash版本。
SHLVL : 每次有Bash执行时,数字加一。
RANDOM : 每次这个参数被用到时,就会产生一个乱数在RANDOM上。
SECONDS : 从这个Shell一开始启动後的时间。
LINENO : Script的行数。
HISTCMD : 历史记录数。
OPTARG : getopts处理的最後一个选项参数。
OPTIND : 下一个要由getopts所处理的参数号码。
HOSTTYPE : 机器种类。
OSTYPE : 作业系统名称。
IFS : Internal Field Separator。
PATH : 命令搜寻路径。
PATH="/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin:."
HOME : 目前使用者的home directory;
CDPATH : cd命令的搜寻路径。
ENV : 如果这个参数被设定,每次有shell script被执行时,将会执行它所设定的档名做为环境设定。
MAIL : 如果这个参数被设定,而且MAILPATH没有被设定,那麽有信件进来时,bash会通知使用者。
MAILCHECK : 设定多久时间检查邮件一次。
MAILPATH : 一串的邮件检查路径。
MAIL_WARNING : 如果有设定的话,邮件被读取後,将会显示讯息。
PS1 : 提示讯息设定,内定为"bash$ "。(请详见提示讯息一节。)
PS2 : 第二提示讯息设定,内定为"> "。
PS3 : select命令所使用的提示讯息。
PS4 : 执行追踪时用的提示讯息设定,内定为"+ "。
HISTSIZE : 命令历史记录量,内定为500。
HISTFILE : 历史记录档,内定~/.bash_history。
HISTFILESIZE : 历史记录档行数最大值,内定500。
OPTERR : 如果设为1,bash会显示getopts的错误。
PROMPT_COMMAND : 如果设定的话,该值会在每次执行命令前都显示。
IGNOREEOF : 将EOF值当成输入,内定为10。
TMOUT : 如果设为大於零,该值被解译为输入等待秒数。若无输入,当成没有输入。
FCEDIT : fc命令的内定编辑器。
FIGNORE : 请详见READLINE。
INPUTRC : readline的startup file,内定~/.inputrc
notify : 如果设定了,bash立即报告被终结的背景程式。
history_control, HISTCONTROL : history使用。
command_oriented_history : 存入多行指令。
glob_dot_filenames : 如果设定了,bash将会把"."包含入档案路径中。
allow_null_glob_expansion : 如果设定了,bash允许路径明称为null string。
histchars : history使用。
nolinks : 如果设定了,执行指令时,不会跟随symbolic links。
hostname_completion_file, HOSTFILE : 包含与/etc/hosts相同格式的档名。
noclobber : 如果设定了,Bash不会覆写任何由">"、">&"及"<>"所操作的档案。
auto_resume : 请见任务控制一节。
no_exit_on_failed_exec : 如果该值存在,非互动的shell不会因为exec失败而跳出。
cdable_vars : 如果启动,而cd命令找不到目录,可切换到参数形态指定的目录下。(linux知识宝库) 



内容简介:
1、vi 及其使用(高兴誉、赵礼)
2、Shell 简述(刘歆)
3、变量及注释(刘歆)
4、最简单的例子(刘歆)
5、流程控制(阴小波)
6、函数(阴小波)
7、实例及其分析(阴小波)
8、感谢及答疑(阴小波)
Vi 简介
vi 是个可视化的编辑器(visual edit). vi 是UNIX 下面的缺省编辑器。 Vi 提供两种操作模
式: 输入模式(insert mode),指令模式(command mode).当使用者进入vi 后,即处于指
令模式下,此刻键入任何字皆被视为指令;a 或i 键用来进入输入模式, 在输入模式下,每
个按键代表输入字符,离开输入模式用<ESC>键。
vi 技巧
1. 文件加密 :X
然后系统会提示输入密码,输入密码后存盘退出。
下次编辑时请使用vi -x filename 打开被加密的文件。
2. 上下两行合并 J
删除所有行 dG
交换两个字符位置xp
上下两行调换ddp
注:xp 和ddp 应该理解为删除一个字符(x)和删除一行(dd),然后在p(paste),这样便不需
记新命令了.
3. 从当前位置删除到行尾d$
从当前位置复制到行尾y$
如果要粘贴到其他地方 p 就可以了
4.文件移动
:line1,line2mline3: 将line1–line2 之间的内容移到line3 下 相当于word 的剪切,
:line1,line2tline3: 将line1–line2 之间的内容粘贴到line3 下,相当于word 的粘贴。
:n1,n2w filename:把行N1-N2 之间内容写入新文件filename 中。
5.自动添加字符串 :ab string strings
例如 ":ab usa United States of America" 。
当你在文件里插入 usa 时 ,United States of America 就蹦出来了
6. 替换命令操作 :g/s1/s/s2/s3/g
第一个g 表示对每一个包括s1 的行都进行替换,第二个g 表示对每一个包括s1 的行的
所有的s2 都用s3 替换,s 表示替换,s2 是要被替换的字符串,他可以和s1 相同(如果相同
的话用//代替),s3 是替换字符串
注:在整个文件中替换特定字符串 :%s/old_word/new_word/g
7. 寄存器操作
"?nyy:将当前行及其下n 行的内容保存到寄存器?中,其中?为一个字母,n 为一个数

"?nyw:将当前行及其下n 个字保存到寄存器?中,其中?为一个字母,n 为一个数字
"?nyl:将当前行及其下n 个字符保存到寄存器?中,其中?为一个字母,n 为一个数字
"?p:取出寄存器?中的内容并将其放到光标位置处。这里?可以是一个字母,也可以是
一个数字
ndd:将当前行及其下共n 行文本删除,并将所删内容放到1 号删除寄存器中。
注:vi 还有有编号的删除缓冲区。撤消命令只能恢复上一次的删除,当且仅当这个删除
是最后一次操作。但是,vi 可以把最近9 次删除的内容都放入9 个编号从1 到9 的缓冲区内。
最近一次删除保存在缓冲区1,次近的在缓冲区2,依此类推。例如,"2p 可以放置第二个
删除缓冲区中的内容。
8. 排序
如有一文件,内容为:
333
222
334
444
111
553
554
233
运行命令:%!sort 文件内容为:
111
222
233
333
334
444
553
554
9. vi 环境选项
noautoindent nomodelines noshowmode
autoprint nonumber noslowopen
noautowrite nonovice tabstop=8
nobeautify nooptimize taglength=0
directory=/var/tmp paragraphs=IPLPPPQPP LIpplpipnpbtags=tags /usr/lib/tags
noedcompatible prompt tagstack
noerrorbells noreadonly term=vt100
noexrc redraw noterse
flash remap timeout
hardtabs=8 report=5 ttytype=vt100
noignorecase scroll=11 warn
nolisp sections=NHSHH HUuhsh+c window=23
nolist shell=/bin/ksh wrapscan
magic shiftwidth=8 wrapmargin=0
mesg noshowmatch nowriteany
For C-Shell:
setenv EXINIT "set nu"
For Bourne or Korn Shell:
EXINIT="set nu"; export EXINIT
For Korn Shell Only (alternate method):
typeset -x EXINIT="set nu"
在 .profile 里设置 vi 的环境选项 , 以上均测试过
10. 重复上一次操作 .:
恢复上一次的操作 u
11. :! shell-command 执行SHELL 命令的操作
举例
1.删除文件中的几行
到删除的开始处 ma
到删除的结束处 d’a
2.拷贝文件中的几行
到拷贝的开始处 ma
到拷贝的结束处 y’a
3.替换文件中所有匹配的字符
替换文件中的 lesson 为course
s/lesson/course/g
注意:可能替换含有lesson 的其他词
4.替换文件中一个区域的字符
start_line, end_line %s/lesson/course/g 或者
采用宏的方式
‘a,. %s/lesson/course/g #需要定义宏;’.’是指光标所在行
5.替换一个文件中某些词
比如替换none 为nothing
查找 /none
替换 cw,输入nothing,按键盘Esc
继续查找 n
替换 .
6.重复执行一个shell 命令
编译一个程序
保存编辑后的文件 :w
编译文件 :!make
修改文件后,在保存 :w
再编译 :!!
7.在两个文件互拷贝
第一种方法:
编辑源文件 vi source_file
到拷贝的部分开始处 ma
到拷贝的部分结束处 :.,’a w tempfile
退出当前文件 :q
编辑目的文件 vi dest_file
到拷贝的地方 :r tempfile
第二种方法:
编辑源文件 vi source_file
到拷贝的部分开始处 ma
到拷贝的部分结束处 “ay’a
不退出源文件编辑目的文件 :e dest_file
到拷贝的地方 “ap
vi 命令一览表
1.进入vi 的命令:
vi filename :打开或新建文件,并将光标置于第一行首
vi +n filename :打开文件,并将光标置于第n 行首
vi + filename :打开文件,并将光标置于最后一行首
vi +/pattern filename:打开文件,并将光标置于第一个与pattern 匹配的串处
vi -r filename :在上次正用vi 编辑时发生系统崩溃,恢复filename
vi filename….filename :打开多个文件,依次进行编辑
2.移动光标类命令:
h :光标左移一个字符
l :光标右移一个字符
space:光标右移一个字符
Backspace:光标左移一个字符
k 或Ctrl+p:光标上移一行
j 或Ctrl+n :光标下移一行
Enter :光标下移一行
w 或W :光标右移一个字至字首
b 或B :光标左移一个字至字首
e 或E :光标右移一个字至字尾
) :光标移至句尾
( :光标移至句首
):光标移至段落开头
{:光标移至段落结尾
nG:光标移至第n 行首
n+:光标下移n 行
n-:光标上移n 行
n$:光标移至第n 行尾
H :光标移至屏幕顶行
M :光标移至屏幕中间行
L :光标移至屏幕最后行
0:(注意是数字零)光标移至当前行首
$:光标移至当前行尾
3.屏幕翻滚类命令:
Ctrl+u:向文件首翻半屏
Ctrl+d:向文件尾翻半屏
Ctrl+f:向文件尾翻一屏
Ctrl+b;向文件首翻一屏
nz:将第n 行滚至屏幕顶部,不指定n 时将当前行滚至屏幕顶部。
4.插入文本类命令:
i :在光标前
I :在当前行首
a:光标后
A:在当前行尾
o:在当前行之下新开一行
O:在当前行之上新开一行
r:替换当前字符
R:替换当前字符及其后的字符,直至按ESC 键
s:从当前光标位置处开始,以输入的文本替代指定数目的字符
S:删除指定数目的行,并以所输入文本代替之
ncw 或nCW:修改指定数目的字
nCC:修改指定数目的行
5.删除命令:
ndw 或ndW:删除光标处开始及其后的n-1 个字
do:删至行首
d$:删至行尾
ndd:删除当前行及其后n-1 行
x 或X:删除一个字符,x 删除光标后的,而X 删除光标前的
Ctrl+u:删除输入方式下所输入的文本
6.搜索及替换命令:
/pattern:从光标开始处向文件尾搜索pattern
?pattern:从光标开始处向文件首搜索pattern
n:在同一方向重复上一次搜索命令
N:在反方向上重复上一次搜索命令
:s/p1/p2/g:将当前行中所有p1 均用p2 替代
:n1,n2s/p1/p2/g:将第n1 至n2 行中所有p1 均用p2 替代
:g/p1/s//p2/g:将文件中所有p1 均用p2 替换
7.选项设置:
all:列出所有选项设置情况
term:设置终端类型
ignorance:在搜索中忽略大小写
list:显示制表位(Ctrl+I)和行尾标志($)
number:显示行号
report:显示由面向行的命令修改过的数目
terse:显示简短的警告信息
warn:在转到别的文件时若没保存当前文件则显示NO write 信息
nomagic:允许在搜索模式中,使用前面不带“\”的特殊字符
nowrapscan:禁止vi 在搜索到达文件两端时,又从另一端开始
mesg:允许vi 显示其他用户用write 写到自己终端上的信息
8.最后行方式命令:
:n1,n2 co n3:将n1 行到n2 行之间的内容拷贝到第n3 行下
:n1,n2 m n3:将n1 行到n2 行之间的内容移至到第n3 行下
:n1,n2 d :将n1 行到n2 行之间的内容删除
:w :保存当前文件
:e filename:打开文件filename 进行编辑
:x:保存当前文件并退出
:q:退出vi
:q!:不保存文件并退出vi
:!command:执行shell 命令command
:n1,n2 w!command:将文件中n1 行至n2 行的内容作为command 的输入并执行之,若不指
定n1,n2,则表示将整个文件内容作为command 的输入
:r!command:将命令command 的输出结果放到当前行
9.寄存器操作:
"?nyy:将当前行及其下n 行的内容保存到寄存器?中,其中?为一个字母,n 为一个数字
"?nyw:将当前行及其下n 个字保存到寄存器?中,其中?为一个字母,n 为一个数字
"?nyl:将当前行及其下n 个字符保存到寄存器?中,其中?为一个字母,n 为一个数字
"?p:取出寄存器?中的内容并将其放到光标位置处。这里?可以是一个字母,也可以是一
个数字
ndd:将当前行及其下共n 行文本删除,并将所删内容放到1 号删除寄存器中。
Shell 编程
如何开始:
如同其他语言一样,通过我们使用任意一种文字编辑器,比如nedit、kedit、emacs、
vi 等来编写我们的shell 程序。程序必须以下面的行开始(必须方在文件的第一行):
#!/bin/sh
符号#!用来告诉系统它后面的参数是用来执行该文件的程序。在这个例子中我们使用
/bin/sh 来执行程序。当编辑好脚本时,如果要执行该脚本,还必须使其可执行。要使脚本
可执行:
chmod +x filename
然后,您可以通过输入: ./filename 来执行您的脚本。
注释:
在进行shell 编程时,以#开头的句子表示注释,直到这一行的结束。我们真诚地建
议您在程序中使用注释。如果您使用了注释,那么即使相当长的时间内没有使用该脚本,您
也能在很短的时间内明白该脚本的作用及工作原理。
变量:
在其他编程语言中您必须使用变量。在shell 编程中,所有的变量都由字符串组成,
并且您不需要对变量进行声明。要赋值给一个变量,您可以这样写:
变量名=值
取出变量值可以加一个美元符号($)在变量前面,如:
$HOME
四、实例:
#!/bin/sh
a="hello world"
echo "A is:"
echo $a
在您的编辑器中输入以上内容,然后将其保存为一个文件first。之后执行
chmod +x first
使其可执行,最后输入./first 执行该脚本。这个脚本将会输出:
A is:
hello world
有许多变量是系统自动设定的,这将在后面使用这些变量时进行讨论。如果您需要处理数学
表达式,那么您需要使用诸如expr 等程序(见下面)。除了一般的仅在程序内有效的shell
变量以外,还有环境变量。由export 关键字处理过的变量叫做环境变量。我们不对环境变
量进行讨论,因为通常情况下仅仅在登录脚本中使用环境变量。
五、Shell 命令和流程控制
在shell 脚本中可以使用三类命令:
1)Unix 命令:
虽然在shell 脚本中可以使用任意的unix 命令,但是还是由一些相对更常用的命令。
这些命令通常是用来进行文件和文字操作的。
常用命令语法及功能
echo "some text": 将文字内容打印在屏幕上
ls: 文件列表
wc –l file 计算文件行数
wc -w file 计算文件中的单词数
wc -c file: 计算文件中的字符数
cp sourcefile destfile: 文件拷贝
mv oldname newname : 重命名文件或移动文件
rm file: 删除文件
grep ‘pattern’ file: 在文件内搜索字符串比如:grep ’searchstring’ file.txt
cut -b colnum file: 指定欲显示的文件内容范围,并将它们输出到标准输出设备比如:
输出每行第5 个到第9 个字符cut -b5-9 file.txt 千万不要和cat 命令混淆,这是两个完
全不同的命令
cat file.txt: 输出文件内容到标准输出设备(屏幕)上
file somefile: 得到文件类型
read var: 提示用户输入,并将输入赋值给变量
sort file.txt: 对file.txt 文件中的行进行排序
expr: 进行数学运算Example: add 2 and 3expr 2 "+" 3
find: 搜索文件比如:根据文件名搜索find . -name filename -print
tee: 将数据输出到标准输出设备(屏幕) 和文件比如:somecommand | tee outfile
sed: Sed 是一个基本的查找替换程序。可以从标准输入(比如命令管道)读入文本,
并将结果输出到标准输出(屏幕)。该命令采用正则表达式(见参考)进行搜索。不要和shell
中的通配符相混淆。比如:将linuxfocus 替换为 LinuxFocus :cat text.file | sed
’s/linuxfocus/LinuxFocus/’ > newtext.file
2) 概念: 管道, 重定向和 backtick
这些不是系统命令,但是他们真的很重要。
管道 (|) 将一个命令的输出作为另外一个命令的输入。
grep "hello" file.txt | wc -l
在file.txt 中搜索包含有”hello”的行并计算其行数。在这里grep 命令的输出作为wc
命令的输入。当然您可以使用多个命令。
重定向:将命令的结果输出到文件,而不是标准输出(屏幕)。
> 写入文件并覆盖旧文件
>> 加到文件的尾部,保留旧文件内容。
反短斜线:使用反短斜线可以将一个命令的输出作为另外一个命令的一个命令行参数。
命令:find . -mtime -1 -type f -print
用来查找过去24 小时(-mtime –2 则表示过去48 小时)内修改过的文件。如果您想
将所有查找到的文件打一个包,则可以使用以下脚本:
#!/bin/sh
# The ticks are backticks (`) not normal quotes (‘):
tar -zcvf lastmod.tar.gz `find . -mtime -1 -type f -print`
3) 流程控制
a. "if" 表达式 如果条件为真则执行then 后面的部分:
if ….; then
….
elif ….; then
….
else
….
fi
大多数情况下,可以使用测试命令来对条件进行测试。比如可以比较字符串、判断文件
是否存在及是否可读等等…通常用" [ ] "来表示条件测试。注意这里的空格很重要。要确
保方括号的空格。
[ -f "somefile" ] :判断是否是一个文件
[ -x "/bin/ls" ] :判断/bin/ls 是否存在并有可执行权限
[ -n "$var" ] :判断$var 变量是否有值
[ "$a" = "$b" ] :判断$a 和$b 是否相等
*)执行man test 可以查看所有测试表达式可以比较和判断的类型。
直接执行以下脚本:
#!/bin/sh
if [ "$SHELL" = "/bin/bash" ]; then
echo "your login shell is the bash (bourne again shell)"
else
echo "your login shell is not bash but $SHELL"
fi
变量$SHELL 包含了登录shell 的名称,我们和/bin/bash 进行了比较。
b. case 表达式可以用来匹配一个给定的字符串,而不是数字。
case … in
…) do something here ;;
esac
让我们看一个例子。 file 命令可以辨别出一个给定文件的文件类型,比如:
file lf.gz
这将返回:
lf.gz: gzip compressed data, deflated, original filename,
last modified: Mon Aug 27 23:09:18 2001, os: Unix
我们利用这一点写了一个叫做smartzip 的脚本,该脚本可以自动解压bzip2, gzip 和zip
类型的压缩文件:
#!/bin/sh
ftype=`file "$1"`
case "$ftype" in
"$1: Zip archive"*)
unzip "$1" ;;
"$1: gzip compressed"*)
gunzip "$1" ;;
"$1: bzip2 compressed"*)
bunzip2 "$1" ;;
*) error "File $1 can not be uncompressed with smartzip";;
esac
您可能注意到我们在这里使用了一个特殊的变量$1。该变量包含了传递给该程序的第一
个参数值。也就是说,当我们运行:
smartzip articles.zip
$1 就是字符串 articles.zip
c. while-loop 将运行直到表达式测试为真。will run while the expression that we test
for is true. 关键字"break" 用来跳出循环。而关键字”continue”用来不执行余下的部
分而直接跳到下一个循环。
d. for-loop 表达式查看一个字符串列表 (字符串用空格分隔) 然后将其赋给一个变量:
for var in ….; do
….
done
在下面的例子中,将分别打印ABC 到屏幕上:
#!/bin/sh
for var in A B C ; do
echo "var is $var"
done
######引号#######
在向程序传递任何参数之前,程序会扩展通配符和变量。这里所谓扩展的意思是程序会把通
配符(比如*)替换成合适的文件名,它变量替换成变量值。为了防止程序作这种替换,您
可以使用引号:让我们来看一个例子,假设在当前目录下有一些文件,两个jpg 文件,
mail.jpg 和tux.jpg。
#!/bin/sh
echo *.jpg
这将打印出"mail.jpg tux.jpg"的结果。
引号 (单引号和双引号) 将防止这种通配符扩展:
#!/bin/sh
echo "*.jpg"
echo ‘*.jpg’
这将打印"*.jpg" 两次。
Here documents
当要将几行文字传递给一个命令时,here documents 一种不错的方法。对每个脚本写一段
帮助性的文字是很有用的,此时如果我们有那个here documents 就不必用echo 函数一行行
输出。 一个 "Here document" 以 << 开头,后面接上一个字符串,这个字符串还必须出
现在here document 的末尾。下面是一个例子,在该例子中,我们对多个文件进行重命名,
并且使用here documents 打印帮助:
#!/bin/sh
# we have less than 3 arguments. Print the help text:
if [ $# -lt 3 ] ; then
cat <<HELP
ren — renames a number of files using sed regular expressions
USAGE: ren ‘regexp’ ‘replacement’ files…
EXAMPLE: rename all *.HTM files in *.html:
ren ‘HTM$’ ‘html’ *.HTM
HELP
exit 0
fi
OLD="$1"
NEW="$2"
# The shift command removes one argument from the list of
# command line arguments.
shift
shift
# $* contains now all the files:
for file in $*; do
if [ -f "$file" ] ; then
newfile=`echo "$file" | sed "s/${OLD}/${NEW}/g"`
if [ -f "$newfile" ]; then
echo "ERROR: $newfile exists already"
else
echo "renaming $file to $newfile …"
mv "$file" "$newfile"
fi
fi
done
这是一个复杂一些的例子。让我们详细讨论一下。第一个if 表达式判断输入命令行参数是
否小于3 个 (特殊变量$# 表示包含参数的个数) 。如果输入参数小于3 个,则将帮助文字
传递给cat 命令,然后由cat 命令将其打印在屏幕上。打印帮助文字后程序退出。 如果输
入参数等于或大于3 个,我们就将第一个参数赋值给变量OLD,第二个参数赋值给变量NEW。
下一步,我们使用shift 命令将第一个和第二个参数从参数列表中删除,这样原来的第三个
参数就成为参数列表$*的第一个参数。然后我们开始循环,命令行参数列表被一个接一个地
被赋值给变量$file。接着我们判断该文件是否存在,如果存在则通过sed 命令搜索和替换
来产生新的文件名。然后将反短斜线内命令结果赋值给newfile。这样我们就达到了我们的
目的:得到了旧文件名和新文件名。然后使用mv 命令进行重命名。


here documents 的结构,可以将用户需要通过键盘输入的字符串改为从程序体中直接读入,如密码。下面的小程序演示了这个功能:

#!/bin/bash



passwd="aka@tsinghua"


ftp -n localhost <<FTPFTP


user anonymous $passwd


binary


bye


FTPFTP




exit 0

这个程序在用户需要通过键盘敲入一些字符时,通过程序内部的动作来模拟键盘输入。请注意 here documents 的基本结构为:

command <<SOMESPECIALSTRING

statments



SOMESPECIALSTRING

这里要求在需要键盘输入的命令后,直接加上 <<符号,然后跟上一个特别的字符串,在该串后按顺序输入本来应该由键盘输入的所有字符,在所有需要输入的字符都结束后,重复一遍前面
<<符号后的“特别的字符串”即表示该输入到此结束。


六、函数
如果您写了一些稍微复杂一些的程序,您就会发现在程序中可能在几个地方使用了相同
的代码,并且您也会发现,如果我们使用了函数,会方便很多。一个函数是这个样子的:
functionname()
{
# inside the body $1 is the first argument given to the function
# $2 the second …
body
}
您需要在每个程序的开始对函数进行声明,在后面的例子中再详细介绍。
七、实例
现在我们来讨论编写一个脚本的一般步骤。任何优秀的脚本都应该具有帮助和输入参
数。并且写一个伪脚本(framework.sh),该脚本包含了大多数脚本都需要的框架结构,是
一个非常不错的主意。这时候,在写一个新的脚本时我们只需要执行一下copy 命令:
cp framework.sh myscript,然后再插入自己的函数。
让我来看一个具体的例子:二进制到十进制的转换
脚本 b2d 将二进制数 (比如 1101) 转换为相应的十进制数。这也是一个用expr 命令
进行数学运算的例子:
#!/bin/sh
# vim: set sw=4 ts=4 et:
help()
{
cat <<HELP
b2h — convert binary to decimal
USAGE: b2h [-h] binarynum
OPTIONS: -h help text
EXAMPLE: b2h 111010
will return 58
HELP
exit 0
}
error()
{
# print an error and exit
echo "$1"
exit 1
}
lastchar()
{
# return the last character of a string in $rval
if [ -z "$1" ]; then
# empty string
rval=""
return
fi
# wc puts some space behind the output this is why we need sed:
numofchar=`echo -n "$1" | wc -c | sed ’s/ //g’ `
# now cut out the last char
rval=`echo -n "$1" | cut -b $numofchar`
}
chop()
{
# remove the last character in string and return it in $rval
if [ -z "$1" ]; then
# empty string
rval=""
return
fi
# wc puts some space behind the output this is why we need sed:
numofchar=`echo -n "$1" | wc -c | sed ’s/ //g’ `
if [ "$numofchar" = "1" ]; then
# only one char in string
rval=""
return
fi
numofcharminus1=`expr $numofchar "-" 1`
# now cut all but the last char:
rval=`echo -n "$1" | cut -b 0-${numofcharminus1}`
}
while [ -n "$1" ]; do
case $1 in
-h) help;shift 1;; # function help is called
–) shift;break;; # end of options
-*) error "error: no such option $1. -h for help";;
*) break;;
esac
done
# The main program
sum=0
weight=1
# one arg must be given:
[ -z "$1" ] && help
binnum="$1"
binnumorig="$1"
while [ -n "$binnum" ]; do
lastchar "$binnum"
if [ "$rval" = "1" ]; then
sum=`expr "$weight" "+" "$sum"`
fi
# remove the last position in $binnum
chop "$binnum"
binnum="$rval"
weight=`expr "$weight" "*" 2`
done
echo "binary $binnumorig is decimal $sum"
#
该脚本使用的算法是利用十进制和二进制数权值 (1,2,4,8,16,..),比如二进制"10"
可以这样转换成十进制: 0 * 1 + 1 * 2 = 2
为了得到单个的二进制数我们是用了lastchar 函数。该函数使用wc –c 计算字符个
数,然后使用cut 命令取出末尾一个字符。Chop 函数的功能则是移除最后一个字符。
我们希望您现在可以开始写您自己的shell 脚本,希望



BASH 程序的调试

用 bash -x bash-script 命令,可以查看一个出错的 BASH 脚本到底错在什么地方,可以帮助程序员找出脚本中的错误。

另外用 trap 语句可以在 BASH 脚本出错退出时打印出一些变量的值,以供程序员检查。trap 语句必须作为继 "#!/bin/bash"
后的第一句非注释代码,一般 trap 命令被写作: trap ‘message $checkvar1 $checkvar2′
EXIT 。

pr
tac
nl
cut
tr

2005年08月21日

你首先需要的是创建一个签名,一个属于你自己的签名。在命令行的模式下执行:

gpg –gen-key

然后按照提示输入相应的信息就可以了,我建议不要输入comment的信息,这样会带来一些麻烦。需要必须输入的信息主要有:full name,comment和email,这三个信息就会构成full name (comment) <email>的格式。建议不要输入comment的信息。在这一步将会要你输入一个私密的口令,这个口令一定要记住,不能忘掉,否则你的这个pgp key就失效了。

生成好你的key之后,下一步就是将它发布到互联网上。发布互联网上,首先需要一个key server,一般安装好后的默认key server都是subkeys.pgp.net。你也可以通过修改.gnupg/gpg.conf中的keyserver信息来改变你的key server。通过如下命令可以将你的key发布到服务器上:

gpg –send-keys YourKeyID

这将会把你的公匙发布到互联网上。你可以到互联网上的某一个key server主页去查询看看你的key是否已经发布到服务器上了,也可以通过gpg –search-keys来查找你的Key是否已经发布到服务器上。

KeyID可以通过 gpg –list-keys来获得。以下是一个输出结果:

pub 1024D/C5852939 2005-02-28
uid Wing sun <chunyang.sun@sw-linux.com>
sub 2048g/4782DB2D 2005-02-28
其中C5852939就是Key ID。

这样你就好了一个Key,接下来你就可以和别人进行Key sign了。

key sign是一个其他人确认且认可你的Key是一个可信任的安全Key的过程。一般而言在国际上进行Key sign的过程是这样的:

1、你需要向他人提供你的Key ID、Full Name、Comment、Email等信息。

2、提供能证明你的身份的证件,一般而言是身份证、护照等有效证件。

3、双方交换这些相关的信息,别且详细检查对方的身份证件,并确认该身份证件就是属于对方的,且确认对方提供的信息是正确的,且属于他自己的。

4、通过PGP的软件完成sign的过程。

通过gnupg进行操作的过程如下:

首先,在你确认了该key的主人身份后,你必须先从互联网上获得该用户的公钥。运行

gpg –recv-keys KeyID

可以获得相应的用公钥信息到本地,当然你也可以通过gpg –search-keys来找寻并获取用户的公钥。

接下来我们就需要对该用户的公钥进行签名,执行

gpg –sign-key KeyID

gnupg将会提示你进行用户公钥的签名验证过程,根据提示进行操作即可。

签名完成后,你需要将你签名后的结果重新发送到互联网上,再一次执行:

gpg –send-keys

将所有的公钥发送到互联网上。

这样你就完成了一个gpg签名的过程。

怎样修改一个错误gpg 密钥?

可能你在创建gpg密钥的时候由于不小心输入错误了,而当你发现输入错误的时候,你却已经将该密钥发送出去了。这时候你可以通过

gpg –edit-key KeyID

来编辑这个密钥,在这个密钥中创建一个新的User ID(通过edit-key的子命令adduid来完成),然后将原有的User ID作废掉(先通过uid命令选中原有的User ID,然后通过revuid来作废该User ID),最后将你的修改发送到互联网上的Key Server即可。

这儿要注意的是,你做过的任何关于密钥的变更(包括修改、签名、作废等)都需要在最后发送到互联网的Key Server才可以确保它完全的生效。

备份你的密钥或者将密钥从一台计算机转移到另外一台

备份密钥分为备份公钥和私钥两个部分,备份公钥:

gpg -o keyfilename –export KeyID

如果没有KeyID则是备份所有的公钥,-o表示输出到文件keyfilename中,如果加上-a的参数则输出文本格式的信息,否则输出的是二进制格式信息。

备份私钥:

gpg -o keyfilename –export-secret-keys KeyID

如果没有KeyID则是备份所有的私钥,-o表示输出到文件keyfilename中,如果加上-a的参数则输出文本格式的信息,否则输出的是二进制格式信息。

然后在别的机器上可以通过

gpg –import filename

导入这些信息。

如果你使用的是相同的系统,则你可以通过最简单的方法将gpg的所有信息拷贝到另外一台计算机上。也就是说你只需要把.gnupg目录完全拷贝到你要拷贝的机器上即可。

如果你丢失了你的私钥,那么你就失去了对该密钥的控制权,因此请保护好你的私钥,将其存储于一个安全的场所。




1.生成密钥

在使用GPG之前,必须生成一对密钥。

[root@tipy root]$ gpg –gen-key

在这之后,你将被问选择哪种加密方式 DAS AND EIGamal, DAS ,EIGAMAL。

第一个是默认的,它包括GPG的全部特性。一般我们都选择它。



接下来它会问你想要的keysize,默认的keysize是1024 bits(一般都用它),我们

就选它。当然你还可以选择其它的,像2048…..。取决于你的需要。



下一步是设置密码的时间限制。如果不需要密码期限的话就选 0。而如果需要的话就选其它的,比如 1y 是指一年,还可以指定是天数,周数,月数。



后一步就是输入你的个人信息了,用户ID 由三个部分组成:真名,注解,和Email地址。只有一个一个输入就行了。



最后一步是输入密码(passphrase),这个密码是解密的时候用的,必须牢记哦。

重复输入一次就over了。



我们可以输入gpg –list-keys 查看我们的key 的信息



2 使用 GnuPG

一 加密

在生成密钥之后,我们就可以开始使用GPG来加密文件了。创建一个文本文件

test.file,输入一些字符,然后保存。

[root@tipy root]$ gpg -ea -r name test.file

其中name是你在上面用来生成密钥时输入的用户名,用这个用户名加密的文件

只能由这个用户名来解密。回车之后就会生成一个

test.file.asc的文件,这个就是加密之后的文件。-e 选项告诉GPG进行加密,

-a 选项告诉GPG加密成ASCII,这样适合邮件发送,而且还可以查看。如果不

是加密成ASCII形式,可以加密成二进制。-r 指定加密的用户。



二 解密

[root@tipy root]$ gpg -d test.file.asc >test.file

敲入回车以后,会要求你输入密码,只有输入上面生成密钥时的那个密码就行了

gpg-list-secret-keys
  查看自己的公钥
  Linux$ gpg-list-keys
  9.用同样的方法在另一台机器上安装gpg,并使用下列命令导出公钥
  Linus$ gpg-export>machine2.asc
  公钥的名字一定要以asc为扩展名,把将这个文件传到你的机器上
  10.在你的机器上使用下列命令将对方的公钥导入
  Linux$ gpg-import machine2.asc
  并再次用gpg-list-keys命令看是否成功导入了对方的公钥
  
  11.接下来我们用做的就是对这把新导入的公钥签名
  Linux$ gpg-sign-key machine2
  注:这里machine2应是对方建立密钥的real name
  我们可以利用pgp-list-sigs来查看是否正确地对对方公钥签名了
  采用同样的方法将你的公钥导出传到对方的机器上
  12.这样我们就可以用对方的公钥来加密文件了;首先建立一个文件
  Linux$ eacho this is a test .>encryptfile
  13.用对方的公钥来加密此文件
  Linux$ gpg-encypt-r receiver_public_keyname encryptfile
  receiver_public_keyname在这里应为接收者的公钥名字;执行完毕后,会生成
  加密后的文件encryptfile.gpg,我们cat encryptfile.gpg输出结果,看看怎样!
  14.将此加密后的文件传到对方机器上,接收方用下命令解密
  gpg –decrypt encryptfile.gpg
  输入正确的passphrase后,会生成解密后的encryptfile文件。

# touch -t 200411280000.00 /tmp/comparison
# find / \( -newer /tmp/comparison -o -cnewer /tmp/comparison \) -ls
2005年08月10日

第一种方法是查看用户shell的命令历史,例如 bash是 ~/.bash_history 但是对于使用csh

2005年08月05日

在grub.conf文件的kernel一行后添加:

console=ttyS0,115200 console=tty0

2005年08月01日

修改/etc/i18n文件即可, i18n内容可以通过 locale -a 来查看支持的所有语言

在/usr/share/zoneinfo/目录下,找到期望的时区,拷贝覆盖/etc/localtime ,然后reboot即可得到新的时区

2005年07月23日
VI命令可以说是Unix/Linux世界里最常用的编辑文件的命令了,但是因为它的命令集众多,很多人都不习惯使用它,其实您只需要掌握基本命令,然后加以灵活运用,就会发现它的优势,并会逐渐喜欢使用这种方法。本文旨在介绍VI的一些最常用命令和高级应用技巧。 

一、基本命令介绍 

---- 1.光标命令 

k、j、h、l——上、下、左、右光标移动命令。虽然您可以在Linux中使用键盘右边的4个光标键,但是记住这4个命令还是非常有用的。这4个键正是右手在键盘上放置的基本位置。
nG——跳转命令。n为行数,该命令立即使光标跳到指定行。
Ctrl+G——光标所在位置的行数和列数报告。
w、b——使光标向前或向后跳过一个单词。
---- 2.编辑命令
i、a、r——在光标的前、后以及所在处插入字符命令(i=insert、a=append、r=replace)。
cw、dw——改变(置换)/删除光标所在处的单词的命令 (c=change、d=delete)。
x、d$、dd——删除一个字符、删除光标所在处到行尾的所有字符以及删除整行的命令。
---- 3.查找命令
---- /string、?string——从光标所在处向后或向前查找相应的字符串的命令。
---- 4.拷贝复制命令
---- yy、p——拷贝一行到剪贴板或取出剪贴板中内容的命令。 

二、常见问题及应用技巧 

---- 1.在一个新文件中读/etc/passwd中的内容,取出用户名部分。
---- vi file
---- :r /etc/passwd 在打开的文件file中光标所在处读入/etc/passwd
---- :%s/:.*//g 删除/etc/passwd中用户名后面的从冒号开始直到行尾的所有部分。
---- 您也可以在指定的行号后读入文件内容,例如使用命令“:3r /etc/passwd”从新文件的第3行开始读入 /etc/passwd的所有内容。
---- 我们还可以使用以下方法删掉文件中所有的空行及以#开始的注释行。
---- #cat squid.conf.default | grep -v '^$' | grep -v '^#' 

---- 2.在打开一个文件编辑后才知道登录的用户对该文件没有写的权限,不能存盘,需要将所做修改存入临时文件。
---- vi file
---- :w /tmp/1 保存所做的所有修改,也可以将其中的某一部分修改保存到临时文件,例如仅仅把第20~59行之间的内容存盘成文件/tmp/1,我们可以键入如下命令。
---- vi file
---- :20,59w /tmp/1 

---- 3.用VI编辑一个文件,但需要删除大段的内容。
---- 首先利用编辑命令“vi file”打开文件,然后将光标移到需要删除的行处按Ctrl+G显示行号,再到结尾处再按Ctrl+G,显示文件结尾的行号。
---- :23,1045d 假定2次得到的行号为23和1045,则把这期间的内容全删除,也可以在要删除的开始行和结束行中用ma、mb命令标记,然后利用“:'a,'bd”命令删除。 

---- 4.在整个文件的各行或某几行的行首或行尾加一些字符串。
---- vi file
---- :3,$s/^/some string / 在文件的第一行至最后一行的行首插入“some string”。
---- :%s/$/some string/g 在整个文件每一行的行尾添加“some string”。
---- :%s/string1/string2/g 在整个文件中替换“string1”成“string2”。
---- :3,7s/string1/string2/ 仅替换文件中的第3行到第7行中的“string1”成“string2”。
---- 注意: 其中s为substitute,%表示所有行,g表示global。 

---- 5.同时编辑2个文件,拷贝一个文件中的文本并粘贴到另一个文件中。
---- vi file1 file2
---- yy 在文件1的光标处拷贝所在行
---- :n 切换到文件2 (n=next)
---- p 在文件2的光标所在处粘贴所拷贝的行
---- :n 切换回文件1 

---- 6.替换文件中的路径。
---- 使用命令“:%s#/usr/bin#/bin#g”可以把文件中所有路径/usr/bin换成/bin。也可以使用命令“:%s//usr/bin//bin/g”实现,其中“”是转义字符,表明其后的“/”字符是具有实际意义的字符,不是分隔符。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta http-equiv="refresh" content="0,url=http://www.sina.com">
</head>
<body bgcolor="#FFFFFF" text="#000000">
</body>
</html>