免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: tanyear
打印 上一主题 下一主题

《UNIX编程环境》学习笔记 [复制链接]

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
11 [报告]
发表于 2005-12-30 01:34 |只看该作者
stty,确实值得研究

论坛徽章:
0
12 [报告]
发表于 2005-12-30 08:54 |只看该作者
楼主,继续!

论坛徽章:
0
13 [报告]
发表于 2005-12-30 12:46 |只看该作者
好,继续啦

第3章 shell的使用

3.1 命令行结构

最简单的命令就是一个字,比如date,who等
一条命令通常以换行结束,也可以用分号;结束

通常有很多个顺序执行的命令可以用;连接
com1;com2;com3

$ set -x
$ date;who|wc
+ date
Fri Dec 30 11:30:10 CST 2005
+ wc
+ who
      1       6      61

注:为了方便看到Shell命令的执行情况,设置了set -x,
输出中以+开头的表示跟踪到的命令执行

;的优先级比较高,所以先执行了date命令,并标准输出;
然后执行who,并通过管道送到wc。

如果需要date和who的输出都送到wc,可以用括号()组合命令
$ (date;who)|wc
+ wc
+ date
+ who
      2      12      90

这样date和who的输出被串连成单个数据流,送入管道

tee命令可以将通过管道的数据流截获并放进某个文件。
$ (date;who)|tee tmp|wc
+ tee tmp
+ wc
+ date
+ who
      2      12      90
$ more tmp
+ more tmp
Fri Dec 30 11:39:19 CST 2005
root     pts/1        Dec 30 08:52
运行tee命令对执行顺序并没有影响,对于管道来说是透明的。
它只是将它的输入复制一份到文件,然后再把输入复制到输出。

另一个命令常用符号&。
&不等命令结束,就将运行的命令放入后台。
用户可以继续与shell交互

$ (sleep 5;date) & date
[1] 7004
+ date
+ sleep 5
Fri Dec 30 11:51:58 CST 2005
$ + date
Fri Dec 30 11:52:03 CST 2005



3.2 元字符

<, >, |, ;和&这些特殊字符,都是由shell来解释的,而不是shell中命令的参数。
在shell中有特殊用途的字符,称为元字符(metacharacter)。

常见的如*代表任何字符串的意思。
不过需要注意,文件名匹配字符串不能匹配以点.开头的的文件名。
以免与.和..相匹配,带来副作用。

$ echo *
+ echo avi rm txt
avi rm txt

$ echo .*
+ echo . .. .bash_logout .bash_profile .bashrc .emacs
. .. .bash_logout .bash_profile .bashrc .emacs

从命令的执行可以看到,由shell解释了*和.*的含义。
而echo程序本身并不了解发生了什么事。

列表一些对于初学者来说,不太常见,但比较有用的元字符:

`...`         运行...中的命令;输出运行结果作为输入
$ `pwd`
++ pwd
+ /home/mysql
-bash: /home/mysql: is a directory

\               \C将C字符作为字符,转义
'...'            ...表示文字
"..."          在...中的$、`...`和\得到解释后,将...作为文本文字
p1&&p2   运行p1;若成功,再运行p2
p1||p2     运行p1;若不成功,再运行p2

具体的一些应用和区别,会在后面慢慢讲。

当元字符不作为元字符使用时,可以有几种方法来表示它们。
防止shell解释元字符最简单的办法就是用单引号'...'

$ echo ***
+ echo avi rm txt
avi rm txt

$ echo '***'
+ echo '***'
***

$ echo \*\*\*
+ echo '***'
***

此外也可以用反斜杠\来转义。
而一种引号也可以保护另一种引号

$ echo "Don't do that"
+ echo 'Don'\''t do that'
Don't do that

这里shell解释的时候自动添加了一个\转义。

$ echo x * y
+ echo x avi rm txt y
x avi rm txt y

$ echo x '*' y
+ echo x '*' y
x * y

$ echo x \* y
+ echo x '*' y
x * y

另外可以在一行末尾加入反斜杠\,表示该行未完,这样可以避免shell中的输入行过长
$ ps -ef| \
> grep java\
> |wc
+ grep java
+ wc
+ ps -ef
      2      28     441

另外关于echo的一个选项 -n,表示不换行。
$ echo -n haha
+ echo -n haha
haha$

如果要echo出-n。可以使用这样的方式
$echo '-n
>'
+ echo '-n
'
-n

[ 本帖最后由 tanyear 于 2005-12-30 14:44 编辑 ]

论坛徽章:
0
14 [报告]
发表于 2005-12-31 02:44 |只看该作者
3.3 位置变量(命令参数)

首先介绍$0,$1,$2...$9
$0指正在执行的程序的名字,$1到$9指程序的参数位置,也叫位置变量。
不详述了。
注意$10会被shell解释成$1后面跟一个0。

比较特殊的一个命令参数,$*,它表示所有的参数
但用户超过9个参数时,它比较有用。
无论给出多少参数,或者有无参数,都能正常执行。

一个使用位置变量最简单的例子
用cx来代替chmod +x

# echo 'chmod +x $1'>cx
# sh cx cx
# echo echo Hi >hello
# ./cx hello
# ./hello
Hi

$1指跟在./cx命令后的第一个参数。在这里就是hello
然后将cx移到/usr/bin就可以当作命令到处使用了。

不过还有更简单的办法。就是设置成alias

之前有帖子说Redhat里面有ll命令可以代替list -l

# alias
alias cp='cp -i'
alias l.='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias ls='ls --color=tty'
alias mv='mv -i'
alias rm='rm -i'

其实可以看到,也就是Redhat设置了一个alias而已。
ll='ls -l'
还有ls以点号开头的文件的l.命令,这是昨天说的ls .*的使用

我们也可以用alias设置自己的精简命令,比如cx命令
# alias cx='chmod +x'
验证一下

# echo echo Hello>hi
# cx hi
# ./hi
Hello

如果要取消掉某个alias,使用unalias命令
#unalias cx

[ 本帖最后由 tanyear 于 2006-1-2 11:12 编辑 ]

论坛徽章:
0
15 [报告]
发表于 2006-01-01 18:12 |只看该作者
加油啊~楼主 ~~~~~~~

论坛徽章:
0
16 [报告]
发表于 2006-01-02 08:55 |只看该作者

回复 15楼 muyuking 的帖子

Thanks, I went out for a classmate's party yesterday.
OK, Let's continue to learn "The Unix Programming Environment"

3.4 shell变量

shell变量除了上节的位置变量,还包括环境变量和普通变量(用户自定义变量)

用set命令可以查看当前的环境变量
# set
BASH=/bin/bash
BASH_ENV=/root/.bashrc
BASH_VERSINFO=([0]="2" [1]="05b" [2]="0" [3]="1" [4]="release" [5]="i386-redhat-linux-gnu")
BASH_VERSION='2.05b.0(1)-release'
COLORS=/etc/DIR_COLORS
...
PATH=/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
PIPESTATUS=([0]="0")
PPID=16266

只查看某个环境变量用echo就够了
举最常用的环境变量PATH的例子。
PATH指定了shell查找命令的目录列表,每个目录之间用:分开

# echo $PATH
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin

# PATH=$PATH:/root/path
# echo $PATH
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin:/root/path

一个变量的值与创建它的shell有关,这个值并不会自动地传递给子shell
# x=hello
# echo $x
hello
# bash        //创建子shell
# echo $x
                    //只有换行符
# exit          //ctrl+d 或者exit 退出子shell,回到原来的shell
# echo $x
hello

所以编写shell程序的时候,应该注意运行一个shell程序,一般变量只在当前的子shell中有效。

# echo 'x="Good Bye"
> echo $x'>setx                             //创建一个两行的shell文件,设置变量x
# cat setx
x="Good Bye"
echo $x
# echo $x                   //在当前shell中
hello
# bash setx                //运行setx shell脚本;在setx运行的子shell脚本中,x是Goodbye
Good Bye                    
# echo $x                   //在原shell中,依然是hello
hello

3.5 运行shell程序的几种方式

如果我们需要使用一个shell程序来改变当前的环境变量怎么办呢?
一个典型的例子就是我们安装了一个新的程序,希望利用shell程序或脚本,把它的目录添加到PATH变量中。

# cat ap                                   //这是一个添加PATH,并且打印PATH的简单脚本
PATH=$PATH:/root/path
echo $PATH

# bash ap                                //用bash运行ap,在运行的子shell中,PATH中添加了/root/path
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin:/root/path
# echo $PATH                          //程序运行结束后,在原shell中,PATH不变,没有/root/path
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin

# . ap                                       //用.运行ap
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin:/root/path
# echo $PATH                           //当前的shell的PATH也已经改变。
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin:/root/path

这是运行shell程序的两种不同方式:
bash ap,创建了一个子shell,并运行其中的命令。运行结束退出子shell
. ap的方式并没有创建一个子shell。它是把shell程序里面的命令看作是用户在终端交互式的键入这些命令。
即shell的标准输入被重定向到这个程序。事实上,这个文件只是被读取,而不是被执行。

在这本书写的时候,作者说,目前用.号运行shell程序还不能接受位置变量。我在fc4上面试了一下,现在是可以的。

此外还有用./ ap来运行shell程序的方式。这种方式和bash ap一样,也是创建子shell并运行命令。
不过这种方式需要ap这个shell文件具有可执行权限。

3.6 shell变量传递

如果需要临时改变环境变量,另外一种发方法是,在命令行的命令之前显式的赋值,也即是行内赋值

# echo 'echo $x'> echox
# chmod +x echox
# ./echox
         
# x=hello ./echox
hello
# echo $x

#

这样行内赋值,把x=hello 传给了子shell
所以3.5中add path的ap脚本,如果只是需要在子shell中使用/root/path
也可以采用行内赋值的方式,传给子shell

#vi echopath
echo $PATH
#chmod +x echopath
# echo $PATH
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
# ./ap ./echopath                   //行内赋值
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin:/root/path
# echo $PATH
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin

当希望在子shell中能够访问某个变量的时候,我们可以使用shell的export命令。
# export x=hello
# echo $x
hello
# bash        //创建子shell
# echo $x
hello             //现在子shell也可以访问x变量
#x=hi            //在子shell中改变x的值
#echo $x
hi
# exit          //ctrl+d 或者exit 退出子shell,回到原来的shell
# echo $x    //原shell的x值并没有变化。
hello

export可以看成是把一个变量设置为全局变量。

通常来说,不要贪图方便,把临时的变量都export出来,应该export那些希望出现在所有shell和子shell中的变量。
比如某些程序的PATH路径等。

3.7 怎样使环境变量登录时生效

如果要使整个系统,每个用户登录时的环境变量进行设置,可以修改/etc/profile文件

在/etc/profile文件这个位置中添加下划线的那一行
# Path manipulation                         //这是/etc/profile脚本里面的一个函数。
if [ `id -u` = 0 ]; then                      //判断id -u这个命令执行的结果是不是等于0。id -u是查看登录的id的uid,root的uid是0。
        pathmunge /sbin
        pathmunge /usr/sbin
        pathmunge /usr/local/sbin
        pathmunge /root/path
fi


再次登录就可以发现/root/path已经被自动加进去了
# echo $PATH
/usr/kerberos/sbin:/usr/kerberos/bin:/root/path:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin

或者简单的在/etc/profile里面的export PATH前添加
PATH=$PATH:/root/path
再次登录
# echo $PATH
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/path:/root/bin

这两种方式/root/path的位置不同,这是/etc/profile这个shell程序所决定的。需要仔细了解的话,可以去读读这个shell脚本。

----------------------

如果我们只是针对某个用户的环境变量进行设置,可以在用户的环境配置文件中添加。
比如在用户的$HOME目录下,对于bash来说有这两个文件可以修改
.bash_profile .bashrc
而csh则可以修改
.cshrc

这几个文件,都是很短小的shell,适合初学者阅读。
比如.bash_profile

# more .bash_profile
# .bash_profile

# Get the aliases and functions              //设置aliase。.bashrc文件里面主要包括的是alias设置的信息。
if [ -f ~/.bashrc ]; then                           //判断home目录下,.bashrc文件是否存在,存在则运行它
        . ~/.bashrc
fi

# User specific environment and startup programs            //设置用户特定的环境变量和自启动程序。

PATH=$PATH:$HOME/bin                                        //在这里添加对应的路径就可以了
BASH_ENV=$HOME/.bashrc
USERNAME="root"

export USERNAME BASH_ENV PATH


# more .bashrc
# .bashrc

# User specific aliases and functions

alias rm='rm -i'                               //3.3节所说的自己设置的alias cx='chmod +x'就可以添加到这里,让它每次登录自动生效。
alias cp='cp -i'
alias mv='mv -i'

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

[ 本帖最后由 tanyear 于 2006-1-6 08:38 编辑 ]

论坛徽章:
0
17 [报告]
发表于 2006-01-03 11:41 |只看该作者
3.7 进一步讨论I/O重定向

在缺省状态下,每个程序启动时都会创建3个文件。用“文件描述符”的小字符标识。
标准输入和标准输出分别用0和1表示,经常被重定向到文件和管道。
而2表示标准错误输出,通常被送往终端。

可以使用command 2> file 把标准错误输出重定向到文件(注意2和>之间没有空格)
command 2>&1 把标准错误输出合并到标准输出  这里的&仅仅是一个记号
command 1>&2 也可以把标准输入加入到标准错误输出中。

记得刚开始学shell的时候,想把错误信息保存下来,发现怎么重定向都不行,咔咔,
后来才知道错误信息输出和标准输出是不同的输出。


shell还提供了把命令的标准输入和命令放在一起的功能,这种结构叫here document
这里举一个简单的例子。用一个自动登录ftp的脚本来说明。

# cat 411
ftp -n localhost <<End         //使用ftp -n的选项
user tony tony         //user后跟用户名和密码
ls
quit
End


# bash 411
Please login with USER and PASS.
Please login with USER and PASS.
KERBEROS_V4 rejected as an authentication type
-rw-r-----    1 1017     105         12603 Oct 28 13:57 ACML-EULA.txt
drwxr-xr-x   11 0        0            4096 Dec 12 10:38 ATLAS
#

说明,here document这种结构说明文件的输入就是该文件的一部分,而不是其他文件。
<<指示了这种情况,后面跟的单字(本例为End)用来终止输入。

论坛徽章:
0
18 [报告]
发表于 2006-01-06 08:36 |只看该作者

回复 17楼 tanyear 的帖子

这周比较忙啊。都没时间来看书。
昨天帮自动化的研究生mm找她选修的软件开发环境的复习资料,
结果问我读研同学,发现我们学校计算机研究生的这门课程,用的就是偶看的这本Unix Programming Environment。
那个寒啊,难怪我之前扫描到后面几章发现都是编程了。

所以结束这个帖子。因为其实这本书不太适合系统管理。倒是可以作为一定的补充和提高

[ 本帖最后由 tanyear 于 2006-1-11 19:47 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP