linux_shell笔记(六)

进程是一条命令在linux 上的执行。用户登录时启动的shell ,也是一条命令,或者进程。但用户在命令行中输入一个linux 工具名时,就启动了一个进程。当用户运行一个shell 脚本的时候,系统创建另一个shell 进程,并为脚本中每行命令创建另外的进程。根据用户调用脚本方式的不同,脚本既可以由当前shell 运行(利用'.' 命令),也可以由当前shell 的一个子shell 运行。后一种方式更加普通。如果用户输入一条内置命令如cd ,此时系统并不会创建进程。

>sleep 10 &

>ps -f

>sleep 10 &

>ps -f

选项'-f' 调用ps 时,ps 显示每个进程信息的完整列表。

>pstree

>pstree -p


执行命令

fork sleep 当用户向shell 中输入一行命令时,shell 创建一个子进程来执行这条命令。当子进程执行该条命令期间,父进程转入睡眠状态,等待被唤醒。当子进程的命令执行完毕之后,它将通过其退出状态通知其父进程自己执行成功或失败,然后消逝。父进程被唤醒,然后提示用户输入另一个命令。


后台进程 当通过在命令结尾处加上 & 符号将进程置于后台运行时, shell 创建一个子进程,但是 shell 并不睡眠,也不等待子进程运行完毕。子进程在后台运行独立于他的父进程。

Shell 运行内置命令的时候, shell 并不创建新进程。

默认情况下,变量只适用于进程本地范围。当进程创建一个子进程时,并不将变量传递给它的子进程。使用 export 内置命令可以将变量设为全局而允许子进程的访问。


命令历史机制:它维护了用户最近发出的命令行的列表,这为重新执行列表中任何事件提供了一个便捷的方式。用户也可通过查看历史记录修正错误。

>history | less

>history | tail

>history 10


HISTSIZE 在一次会话期间保存的最大事件数目

HISTFILE 历史文件的位置

HISTFILESIZE 会话之间保存的时间最大数目

>echo $HISTSIZE $HISTFILE $HISTFILESIZE


重新执行和编辑命令 可以重新执行历史列表中的任何事件。内置命令 fc 使用感叹号 使用 Readline


fc 显示编辑和重新执行命令

fix command 修改命令,可用来显示历史列表内容,并可以编辑和重新执行前面的命令。


显示历史列表中的命令,不带参数将显示最近16 个命令。

>fc -l

>fc -l [first [last]]

>fc -l 100 200 | less

>fc -l vim apropos | less

>fc -l 1027 1027


编辑和重新执行前面的命令:

> fc [-e editor] [first [last]]

'-e' 调用fc 时,如果后面还带某个编辑器的名字,那么fc 将调用该编辑器,并将事件放到工作缓冲区中。如果不带firstlast 参数,fc 默认最近命令。如果设置了FCEDIT ,那么没有必要在命令行指定使用的编辑器。

使用vim 编辑最近使用的命令

>fc -e vi

设置FCEDIT 并利用fc 编辑最近使用的命令,使用的编辑器将依照FCEDIT 的设置。

>export FCEDIT=/usr/bin/emacs

>fc

fc 调用编辑器编辑指定命令

>fc 21

调用编辑器编辑以字母vim 开头的最近事件到206 之间的事件出

>fc vim 206

fc 利用编辑器编辑相关命令,退出编辑器的时候, shell 将执行存放在编辑器缓冲区内的任何内容,如果需要不执行命令,那么退出之前需要删除缓冲区中的所有内容。

>echo $PS1

>PS1=”/u@/h:/w/!$”

>ls -li

>fc -e vi

>whereis vim

>export FCEDIT=”/usr/bin/vim”

>fc 509

>fc 500 509


不调用编辑器而重新执行命令

调用 fc 时带上 '-s' 选项那么将跳过编辑阶段而重新执行该命令

>fc-s 509

>fc -s


使用感叹号引用事件

! 除非后面紧接着空格符 换行符 =或者( ,否则立即开始某个历史事件。

!! 前一个命令

!n 历史列表中编号为 n 的命令

!-n 往前第n 条命令

!string 最近以 string 开始的命令行

!?string[?] 包含sting 的最近命令行

!# 当前命令 目前正在输入的部分

!{event} !{-3}3 后跟着3 的第3 个最近执行的命令

>echo example*

>!!

>readelf example

>!! | less

>!515

>history 10

>!whereis

>!?example


字标志符

字标志符指定了事件中的某个字或者一组字。这些字的编号从 0 开始 ( 命令行的第一个字通常是命令名 ) 为了指定前一个事件中的某个字,在事件标识符 (!107) ,后面跟一个冒号和一个表示该字在这个命令中的标号。

n n 个字;字0 为命令名

^ 第一个字,紧跟命令之后

$ 最后那个字

m-n 从编号mn 的所有字

n* n 到最后

* 除命令名以外所有字

>echo $PS1

>PS1='/u@/h:/w-/!/$'

>echo apple grape orange pear

>echo !109:*

>echo !109:2-4

>echo !109:$

>!109

>!109:0-$

>cd example

>cat example.sh

>vim !$

!$ 表示前一个命令的最后一个字。

替换修饰符 语法如下:

[g]s/old/new


>cat exampleji.sh

>!!:s/exampleji/example

快速替换符是^ 。可以用它来执行最近事件同时改变该事件的内容。

>cat exampleji.sh

>^exampleji^example


别名:别名是一种名称, shell 将其翻译成另一个名字或者命令。 定义别名语法如下:

>alias [name[=value]]

如果value 中含有空格或者制表符,需要利用引号将其括起来。别名并不替换自己,这避免了在处理如下别名时可能存在的递归。

>alias ls='ls -F'

unalias 删除别名。 不带参数的alias 将列出当前所有别名的列表。

>alias

单双引号的区别:value 用双引号引起来,那么当创建别名时,value 中任何变量都将扩展。如果将value 用单引号括起来,那么在使用该别名之前变量都不会被扩展。

>alias dirA=”echo working directory is $PWD”

>alias dirB='echo working directory is $PWD'

>alias dirA dirB

>cd ..

>dirA

>dirB

shell 只检查那些简单的,未经引用的命令,看其是否为别名。那些相对或者绝对路径名的命令和引用命令都不被检查。在命令前加反斜杠或者执行命令时使用绝对路径,将不进行别名替换。

>alias

>ls

>/ls

>whereis ls

>/bin/ls


别名示例:

>alias r='fc -s'

>alias l='ls -ltr'

>alias zap='rm -i'

>ls

>r

>l

>zap example*

>alias ls='ls -F'

>alias ll='ls -l'

>ll ( 结果同ls -F -l)


>unalias r l zap ll

>alias

>unalias dirA dirB


函数 shell 函数类似于 shell 脚本,里面存放了一系列可在后期执行的命令。 然而因为shell 函数存放在RAM 而不是磁盘文件中,因此shell 访问函数的速度要比访问脚本速度快得多。shell 函数的执行和调用在同一个shell 中进行的。可以使用 unset 删除 shell 函数。如果 shell 变量和函数同名则 unset 删除 shell 变量,如果再次用相同的名字调用 unset ,就会删除这个函数。

声明函数语法如下:

>[function] function-name() RETURN

{ RETURN

command RETURN

} RETURN


>function whoson() RETURN

{ RETURN

date RETURN

echo “users currently logged on” RETURN

who RETURN

} RETURN

>whoson

>function whoson2() { who; date; } RETURN

>cat >whoson.sh RETURN

date RETURN

echo “users currently logged on” RETURN

who RETURN

COUNTROL+D

>chmod u+x whoson.sh

>./whoson.sh

>set | grep whoson

>function echo_arg() RETURN

{ RETURN

echo “The arg is $1 && $2” RETURN----”” 不可省略

echo The arg is $1 $2 $3

} RETURN

>echo_arg arg1 arg2 arg3

>unset echo_arg whoson


控制shell 的特性:利用 set shopt 控制 shell 特性

有两种类型的命令行选项,短选项和长选项,短选项由一个连字符后面跟一个字母构成,而长选项由两个连字符后面跟多个字母构成。同一命令行上的长选项必须放在短选项之前。

--: 在命令行中表示选项的结束,后面的字将作为参数,即使他们以连字符开头。

shell 特性,可以通过打开或者关闭bash 的功能的方式来控制他的行为。内置命令set 控制一部分功能,shopt 控制另一部分功能。

set +-o 开启和关闭 shell 特性,‘ -o’ 开启特性, '+o' 关闭特性。

>set -o noclobber

>set -o vi

>set +o vi

>set -o

>set +o


>shopt -s

>shopt -u

>shopt -s dotglob

>shopt -u dotglob

'-s' 开启特性, '-u' 关闭特性。


处理命令行:

无论是采取交互式还是运行shell 脚本,bash 在处理命令行之前都需要读取该命令行,即bash 在处理一条命令之前总是读取至少一行命令。如果bash 知道某条命令跨越多行,则在处理该命令之前将读取整条命令。

>echo 'this is RETURN

echo .e.g' RETURN

>function hello() RETURN

{ RETURN

echo hello RETURN

} RETURN

在读取一条命令之后,bash 对该命令应用历史扩展和别名扩展。


历史扩展:bash 将历史命令转换到可执行命令行的过程。对于交互式 shell 历史扩展默认是开启的,使用 'set +o histexpand' 可将其关闭;而非交互式 shell(shell 脚本 ) 不能使用历史扩展。

>!!

>!108


别名替换:别名将一个简单命令的第一个字替换为一个字符串。默认情况下shell 的别名特性是开启的,在非交互式shell 中则是关闭的。使用'shopt -u expand_alias' 可将其关闭。

>alias ls='ls -F'

>ls

>alias

>unalias ls


解析和扫描命令行:在处理完历史命令和别名之后,bash 并不立即执行命令。首先是将命令行解析成标记或者字,然后shell 扫描每个标记,查找特殊字符和模式,shell 需要对他们采取某些动作。进行命令行扩展。


命令行扩展:

在交互式用法和非交互式用法中,shell 在将命令行传递给被调用程序之前均使用命令行扩展。按照下列顺序进行命令行扩展:

花括号扩展

代字符扩展

参数扩展和变量扩展

算数扩展

命令替换

分词

路径名扩展

处理替换


引用删除:在处理完命令行扩展后,bash 将不是扩展结果的单引号 双引号和反斜杠从命令行中删除。称为引用删除。


扩展顺序

bash 执行命令行扩展的步骤的顺序会影响到命令的解释。

>SENDIT=”>/tmp/saveit”

>echo xxx $SENDIT

命令的运行结果是:shell 并不进行输出的重定向,他在计算变量的值之前识别输入输出的重定向。其结果是将'>/tmp/saveit' 最为参数传递给echo

切记双引号和单引号将使 shell 在进行扩展时表现出不同的行为。双引号允许参数和变量的扩展,但是抑制其他类型的扩展,而单引号则抑制所有的扩展。


花括号扩展:当不能利用路径名扩展时,它为指定文件名提供了一个便利方式。尽管花括号扩展主要用于指定文件名,该机制还可以用来产生任意字符串。

花括号扩展在交互式和非交互式 shell 中都是默认开启的。 可使用'set +o braceexpand' 关闭。

>ls

>echo example{1,2,3}.sh

当有较长的前缀或者后缀时,花括号扩展很有用,避免多次输入长的路径名

>cp /usr/local/src/c/{main,f1,f2,tmp}.c .

>mkdir example{A,B,C}

>ls -F

>rmdir example{A,B,C}

>mkdir example[A-C]

>ls

>rmdir example[A-C]


带字符扩展:

当代字符出现在命令行某字的起始处时,它就属于一个特殊的字符。bash 将后面的字符串( 在第一个斜杠之前或者如果没有斜杠,到达字的末尾) 作为一个可能的登录名。如果可能的登录名是空的,那么shell 将用HOME 变量的值取代这个代字符。

>echo $HOME

>echo ~

>echo ~/example.sh

>cp ~/example/example.sh .


如果后面的字符串构成一个合法的登录名,那么shell 将用与该登录名相对应的主目录路径名来替换这个代字符和名字,如果他不为空且不是一个合法的登录名,shell 将不进行任何替换:

>echo ~root

>echo ~terry

>echo ~nouser


参数扩展和变量扩展:

后面没有开放的圆括号的 $ 将引入参数或者变量扩展。参数包括命令行,或者位置参数和特殊参数。变量包括用户创建的变量和关键字变量。

如果参数和变量用单引号引起来或者开头的$ 符号被转义,那么这些参数和变量将不会扩展。



算术扩展:

shell 计算算术表达式的值并用该值替换表达式,这就是算数扩展。

$((expression))

不需要在expression 中的变量名前加上$ 符号。

>cat >age_check.sh RETURN

#!/bin/bash RETURN

echo -n “How old are you?” RETURN

read age RETURN

echo “Wow, in $((60-age)) years, you'll be 60!” RETURN

CONTROL+D

>chmod u+x age_check.sh

>./age_check.sh


>x=2 y=4

>echo $((2*$x+5*$y))

>echo $((2*x+5*y))

>unset x y


>x=3+6 y=4+7

>echo $((x+y))

>echo $x

>x=$((3+6))

>echo $x

>unset x y


命令替换:

利用命令的输出来替换该命令。

$(command)

shell 将在子shell 中执行command 并用command 的标准输出取代command ,连同两边的标点。

>echo $(pwd)

>echo “You are using the $(pwd) directory.”

>echo $(ls -l)

 


分词:

参数和变量扩展,命令替换和算术扩展的结果都可以作为分词的候选者,bash 利用IFS 定义的每个字符作为可能的分割符,将这些候选着划分成字或者标记。


路径名扩展:

路径名扩展又称为文件名生成或者文件名补全,它表示解释模糊文件引用以及替换合适文件名的列表的过程。如果 bash 在处理模糊文件引用时,找不到任何匹配该模式的文件,那么带有模糊文件引用的标记将被保留。

>echo example*

>echo *

>echo example?

>echo .*

>ls .*

>ls *

>echo nofile*


引用:

用双引号把参数括起来将使 shell 抑制路径名扩展和所有除参数扩展和变量扩展之外的其他扩展。而用单引号把参数括起来会抑制所有类型的扩展。

>echo “example* $HOME”

>echo 'example* $HOME'

>echo example* $HOME

>a=example*

>echo $a

>a='example*'

>echo $a

>echo “$a”

>echo '$a'

>unset a


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值