BASH Tips

代码学习

 
:() { :|:& }; :

为什么这个东西会让你的系统死掉???有人执行了然后问我 让我们来分析一下这段代码,我改一下格式,但内容是一样的 代码: :() # 定义一个叫“:”的过程 { # 标记过程内容的开始 : | : & # 执行“:”这个过程,然后通过管道接到“:”再执行一次,而且每一次执行,都会在后台执行 }; # 标记过程内容的结束,因为是同一行来写,所以要加上“;”,这样才能接后面的内容 : # 执行:

两个原因使它死掉: 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的趋势变化。然而产生新进程的速度是极快的,因而在极短的时间内将会产生无数的进程。在这种情况下,死机是很正常的。

random password

#!/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

bash截断字符串

象专业人员那样截断字符串

尽管 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 是第二个,以此类推。

screen 設定

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

快速安装zabbix-agentd的脚本

#!/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
/home1/yepnnet/public_html/wiki/data/pages/bashtips.txt · 最后更改: 2010/09/09 09:24 由 admin
到顶部
CC Attribution-Noncommercial-Share Alike 3.0 Unported
chimeric.de = chi`s home Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0