:() { :|:& }; :
为什么这个东西会让你的系统死掉???有人执行了然后问我 让我们来分析一下这段代码,我改一下格式,但内容是一样的 代码: :() # 定义一个叫“:”的过程 { # 标记过程内容的开始 : | : & # 执行“:”这个过程,然后通过管道接到“:”再执行一次,而且每一次执行,都会在后台执行 }; # 标记过程内容的结束,因为是同一行来写,所以要加上“;”,这样才能接后面的内容 : # 执行:
两个原因使它死掉: 1. 无限递归。倘若只是简单的: &,那么每次递归调用的时候一边在后台执行,而另外一边则在退出。然而,即使如此,倘若你只是下面的内容,你仍然可以看到不少bash,而且是不断地增多。其原因很可能是一边产生新的进程的同时,另外一边的进程却还没完全退出。然而,这种产生方式,终究会在某个时刻达到动态平衡,也就是新产生新进程的速度和结束进程的速度达到平衡。因而,这并不一定会让系统挂掉。 代码: show_ps() { ps -A | grep bash; show_ps & }; show_ps
2. 平衡的破坏 2.1 两个进程同时开始 使用管道的时候,不是一个进程完了然后另外一个进程才开始,而是两个进程同时开始,其中一个进程读取另外一个进程的标准输出作为标准输入。 代码: tee | grep abc
可以看到,这个时候,我们只有输入满足正则表达式abc的内容,它才会被重复。而这个过程会一直持续到我们结束tee的输入。
2.2 死机的原因:同时执行导致平衡的破坏。(注意:这只是一个简化的模型。同时执行只是理想情况,真正在执行的时候,会由于实际情况有所偏差,但由于偏差并不大,所以这个模型仍然可用;另外,现在假设每个“:”都会产生一个进程,然而实际情况是这样的:先: | : &产生一个进程,接着由于两次:的调用进而产生两个进程,再接着: | : &所在的进程消亡,如此循环,显然,实际情况只是比这个模型增加了一些自我抵销的中间环节而已) 在: | : &执行的时候,我们知道,两个“:”是同时执行的。倘若同时有n个“:”在运行,那么,它将首先产生2*n个进程,然后这n个进程再结束掉,此时相当于新增加了2*n个进程。那从第一次调用开始,假设进程产生后马上结束,那么进程数量的变化将呈2^n的趋势变化。然而产生新进程的速度是极快的,因而在极短的时间内将会产生无数的进程。在这种情况下,死机是很正常的。
#!/bin/bash # May need to be invoked with #!/bin/bash3 on older machines. # # Random password generator for bash 2.x by Antek Sawicki <tenox@tenox.tc>, # who generously gave permission to the document author to use it here. # # ==> Comments added by document author ==> MATRIX="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$&*()" LENGTH="10" # ==> May change 'LENGTH' for longer password, of course. while [ "${n:=1}" -le "$LENGTH" ] # ==> Recall that := is "default substitution" operator. # ==> So, if 'n' has not been initialized, set it to 1. do PASS="$PASS${MATRIX:$(($RANDOM%${#MATRIX})):1}" # ==> Very clever, but tricky. # ==> Starting from the innermost nesting... # ==> ${#MATRIX} returns length of array MATRIX. # ==> $RANDOM%${#MATRIX} returns random number between 1 # ==> and length of MATRIX ? 1. # ==> ${MATRIX:$(($RANDOM%${#MATRIX})):1} # ==> returns expansion of MATRIX at random position, by length 1. # ==> See {var:pos:len} parameter substitution in Section 3.3.1 # ==> and following examples. # ==> PASS=... simply pastes this result onto previous PASS (concatenation). # ==> To visualize this more clearly, uncomment the following line # ==> echo "$PASS" # ==> to see PASS being built up, # ==> one character at a time, each iteration of the loop. let n+=1 # ==> Increment 'n' for next pass. done echo "$PASS" # ==> Or, redirect to file, as desired. exit 0
象专业人员那样截断字符串
尽管 basename 和 dirname 是很好的工具,但有时可能需要执行更高级的字符串“截断”,而不只是标准的路径名操作。当需要更强的说服力时,可以利用 bash 内置的变量扩展功能。已经使用了类似于 ${MYVAR} 的标准类型的变量扩展。但是 bash 自身也可以执行一些便利的字符串截断。看一下这些例子:
第一种方法:
${varible##*string} 从左向右截取最后一个string后的字符串 ${varible#*string}从左向右截取第一个string后的字符串 ${varible%%string*}从右向左截取最后一个string后的字符串 ${varible%string*}从右向左截取第一个string后的字符串 "*"只是一个通配符可以不要 $ MYVAR=foodforthought.jpg $ echo ${MYVAR##*fo} rthought.jpg $ echo ${MYVAR#*fo} odforthought.jpg
在 第一个例子中,输入了 ${MYVAR##*fo}。它的确切含义是什么?基本上,在 ${ } 中输入环境变量名称,两个 ##,然后是通配符 (“*fo”)。然后,bash 取得 MYVAR,找到从字符串 “foodforthought.jpg” 开始处开始、且匹配通配符 “*fo” 的 最长 子字符串,然后将其从字符串的开始处截去。刚开始理解时会有些困难,为了感受一下这个特殊的 ”##” 选项如何工作,让我们一步步地看看 bash 如何完成这个扩展。首先,它从 “foodforthought.jpg” 的开始处搜索与 “*fo” 通配符匹配的子字符串。以下是检查到的子字符串:
f fo MATCHES *fo foo food foodf foodfo MATCHES *fo foodfor foodfort foodforth foodfortho foodforthou foodforthoug foodforthought foodforthought.j foodforthought.jp foodforthought.jpg
在搜索了匹配的字符串之后,可以看到 bash 找到两个匹配。它选择最长的匹配,从初始字符串的开始处除去,然后返回结果。
上 面所示的第二个变量扩展形式看起来与第一个相同,但是它只使用一个 ”#” – 并且 bash 执行 几乎 同样的过程。它查看与第一个例子相同的子字符串系列,但是 bash 从初始字符串除去 最短 的匹配,然后返回结果。所以,一查到 “fo” 子字符串,它就从字符串中除去 “fo”,然后返回 “odforthought.jpg”。
这样说可能会令人十分困惑,下面以一简 单方式记住这个功能。当搜索最长匹配时,使用 ##(因为 ## 比 # 长)。当搜索最短匹配时,使用 #。看,不难记吧!等一下,怎样记住应该使用 '#' 字符来从字符串开始部分除去?很简单!注意到了吗:在美国键盘上,shift-4 是 “$”,它是 bash 变量扩展字符。在键盘上,紧靠 “$” 左边的是 ”#“。这样,可以看到:”#” 位于 “$” 的“开始处”,因此(根据我们的记忆法),”#” 从字符串的开始处除去字符。您可能要问:如何从字符串末尾除去字符。如果猜到我们使用美国键盘上紧靠 “$” 右边 的字符 (”%),那就猜对了。这里有一些简单的例子,解释如何截去字符串的末尾部分:
$ MYFOO="chickensoup.tar.gz" $ echo ${MYFOO%%.*} chickensoup $ echo ${MYFOO%.*} chickensoup.tar 正如您所见,除了将匹配通配符从字符串末尾除去之外,% 和 %% 变量扩展选项与 # 和 ## 的工作方式相同。请注意:如果要从末尾除去特定子字符串,不必使用 "*" 字符: MYFOOD="chickensoup" $ echo ${MYFOOD%%soup} chicken
在此例中,使用 ”%%” 或 ”%” 并不重要,因为只能有一个匹配。还要记住:如果忘记了应该使用 ”#” 还是 ”%“,则看一下键盘上的 3、4 和 5 键,然后猜出来。
第二种方法:${varible:n1:n2}:截取变量varible从n1到n2之间的字符串。
可以根据特定字符偏移和长度,使用另一种形式的变量扩展,来选择特定子字符串。试着在 bash 中输入以下行:
$ EXCLAIM=cowabunga $ echo ${EXCLAIM:0:3} cow $ echo ${EXCLAIM:3:7} abunga
这种形式的字符串截断非常简便,只需用冒号分开来指定起始字符和子字符串长度。
应用字符串截断
现在我们已经学习了所有截断字符串的知识,下面写一个简单短小的 shell 脚本。我们的脚本将接受一个文件作为自变量,然后打印:该文件是否是一个 tar 文件。要确定它是否是 tar 文件,将在文件末尾查找模式 ”.tar”。如下所示:
mytar.sh – 一个简单的脚本
#!/bin/bash if [ "${1##*.}" = "tar" ] then echo This appears to be a tarball. else echo At first glance, this does not appear to be a tarball. fi
要运行此脚本,将它输入到文件 mytar.sh 中,然后输入 “chmod 755 mytar.sh”,生成可执行文件。然后,如下做一下 tar 文件试验:
$ ./mytar.sh thisfile.tar This appears to be a tarball. $ ./mytar.sh thatfile.gz At first glance, this does not appear to be a tarball.
好, 成功运行,但是不太实用。在使它更实用之前,先看一下上面使用的 “if” 语句。语句中使用了一个布尔表达式。在 bash 中,”=” 比较运算符检查字符串是否相等。在 bash 中,所有布尔表达式都用方括号括起。但是布尔表达式实际上测试什么?让我们看一下左边。根据前面所学的字符串截断知识,”${1##*.}” 将从环境变量 “1” 包含的字符串开始部分除去最长的 “*.” 匹配,并返回结果。这将返回文件中最后一个 ”.” 之后的所有部分。显然,如果文件以 ”.tar” 结束,结果将是 “tar”,条件也为真。
您可能会想:开始处的 “1” 环境变量是什么。很简单 – $1 是传给脚本的第一个命令行自变量,$2 是第二个,以此类推。
more .screenrc
## エスケープキーの設定
escape ^Tt
## ビジュアルベルを無効
vbell off
## ステータス行の設定
hardstatus ignore "[screen %n] %h"
#hardstatus alwayslastline "[%02c] %`%-w%{=b bw}%n %t%{-}%+w"
caption always "[%02c:%02s] %`%-w%{=b bw}%n %t%{-}%+w"
#caption always "%{= wk} %-w%{=bu dr}%30L>%n %{-}%+w%-18= %{=b wb}|%Y-%m-%d %{=b wb}%02c"
defhstatus "^En:^Et"
termcapinfo * 'hs:ts=\E]2;:fs=\007:ds=\E]0;screen\007'
shelltitle "$ |bash"
## スタートアップ時メッセージ無効
startup_message off
## 自動でデタッチする
autodetach on
## スクロール行を 10,240行
defscrollback 10240
## ^T U で UTF-8 / ^T E で EUC-JP を切り替え
#bind U eval "encoding utf-8" "!!!echo 'export LANG=ja_JP.UTF-8'"
#bind E eval "encoding euc" "!!!echo 'export LANG=ja_JP.EUC-JP'"
encoding utf8
#!/bin/bash zabbix_server_ip="192.168.x.xx" inner_ip=`sudo /sbin/ifconfig eth1 |awk '/inet/ {split($2,x,":");print x[2]}'` tar xvzf zabbix-1.8.2.tar.gz cd zabbix-1.8.2 sudo /usr/sbin/useradd zabbix sudo mkdir -p /var/log/zabbix /opt/app/zabbix /etc/zabbix sudo chown -R zabbix /var/log/zabbix/ ./configure --prefix=/opt/app/zabbix --enable-agent make sudo make install sudo cp misc/conf/zabbix_agentd.conf /etc/zabbix/ sudo cp misc/init.d/fedora/core5/zabbix_agentd /etc/init.d/ sudo /sbin/chkconfig zabbix_agentd on sudo sed -i -e '/^LogFile/s/^.*$/LogFile=\/var\/log\/zabbix\/zabbix_agentd.log/' /etc/zabbix/zabbix_agentd.conf sudo sed -i -e "/Server=127/s/127.0.0.1/${zabbix_server_ip}/" /etc/zabbix/zabbix_agentd.conf sudo sed -i -e "/^Hostname/s/^.*$/Hostname=`hostname`/" /etc/zabbix/zabbix_agentd.conf sudo sed -i -e "/ListenIP=127/s/^.*$/ListenIP=${inner_ip}/" /etc/zabbix/zabbix_agentd.conf #sudo sed -i -e '/^PID=/s/\/var//' /etc/init.d/zabbix_agentd sudo sed -i -e '/^ZABBIX_BIN=/s/usr\/bin/opt\/app\/zabbix\/sbin/' /etc/init.d/zabbix_agentd #sudo sed -i -e '/\$0 stop/asleep 2' /etc/init.d/zabbix_agentd sudo /etc/init.d/zabbix_agentd start ps aux | grep zabbix tail /var/log/zabbix/zabbix_agentd.log