Posts Tagged: bash


28
六 11

bash中getopts的用法

getopts 用于解析命令行参数。
用法: getopts 选项字符串 名称 [参数]
举个例子:
一个a.sh内容如下
#!/bin/bash
usage() {
cat << -EOF-
Usage:
$0 -I interface -i ipaddr

-EOF-
exit 1
}
while getopts “I:i:” opt ; do
case $opt in
I) interface=$OPTARG ;;
i) IP=$OPTARG ;;
?) usage ;;
done

if [[ -z "$interface" || -z "$ip" ]] ; then
usage
else
ifconfig $interface $ip
fi

其中:
1. 选顶字符串中,后面跟”:”(冒号)表示后面要跟一个参数,这个参数应用空格与选项隔开;这个参数保存在OPTARG变量中。
2. 选项字符串以”:”开始,将打开“沉默错误报错方式”,不能识别的选择等,将不打印错误信息。
3. getopts 将使用三个变量:name, OPTIND, OPTARG,OPTERR.
OPTERR :如果OPTERR=0, shell将禁用“错误提示输出”,即使选项字符串的开头不是冒号。
OPTARG : 当getopts解析到“选项”时,将指定的参数保存到这个变量中。
OPTIND : 存储$* 位置参数中的位置,随着getopts的处理而被getopts修改。

  


25
十二 10

bash 4

1. 从 command_not_found_handle 说起

发现Ubuntu(以及openSUSE)都提供了一个非常“友好”的功能:当你输入错误的、不存在的命令的时候,系统(实际上是bash调用应用程序)会给出相当有“建设性的”建议:

hongchuan@ubuntu:~$ gvim
程序“gvim”已包含在下列软件包中:
* vim
* vim-gnome
* vim-tiny
* vim-gtk
* vim-nox
请尝试:sudo apt-get install <选定的软件包>

hongchuan@ubuntu:~$ mc
程序“mc”尚未安装。  您可以使用以下命令安装:
sudo apt-get install mc

不访先思考一下Ubuntu是如何实现这个功能的。

………………………………

是的,要“捕获”这个“错误”,通过bash无疑是最直接和高效的。

……………………

bash 4提供了一个command_not_found_handle“钩子”,当bash遇到“命令找不到”时,假如这个函数被“定义”,则command_not_found_handle $1 被执行。

Ubuntu的command_not_found_handle是这样定义的:

command_not_found_handle () {
if [ -x /usr/lib/command-not-found ]; then
/usr/bin/python /usr/lib/command-not-found — $1;
return $?;
else
if [ -x /usr/share/command-not-found ]; then
/usr/bin/python /usr/share/command-not-found — $1;
return $?;
else
return 127;
fi;
fi
}

/usr/lib/command_not_found是一个用Pythonp写的处理“错误”、并提供“建议”的程序。

随便提一下,我当前的Ubuntu版本是10.10(lsb_release -r ),bash是4.1.5(1)-release(echo $BASH_VERSION),当前系统提供的bash手册中,完全没有提到command_not_found_handle,而GNU网站上的bash手册中则有详细说明:Command-Search-and-Execution

2. Coprocesses (协进程/异步支持)

bash 4新增的内置命令coproc,用于在后台启动一个子shell,并将command放在子shell中执行,在后台执行的进程称作coprocess(协进程)。当前shell不需要等待command执行完成,于是有“异步”之功效。coproc command与command &某种程度上效果相同。

如何使用 coproc :

举个例子,执行  coproc  COMMAND,那么 coproc 会做几件事情:

1.在后台启动子shell,PID值放在变量 COPROC_PID中。
2.在子shell中执行COMMAND。
3.建立两个“双向管通”,管道的文件描述符为${COPROC[0]}和${COPROC[1]}。

这样,就建立了一个“父进程”与“子进程”之间进行通信的方式(管道)。其中 ${COPROC[0]} 连接着“协进程”的“标准输出”,${COPROC[1]}连接着 “协进程”的“标准输入”。父进程通过${COPROC[0]}读取“协进程”的输出,通过${COPROC[1]}向子进程发送数据。

应用举例:
#!/bin/bash
rw() {
while read line ; do
echo $line >> log.txt
done
}
coproc  rw
cat >&${COPROC[1]}

这个程序在前台启动一个cat,后台启动一个read的循环,读取前台的输入并将输入写入log.txt文件。

另一个:

#!/bin/bash
process_line() {
local line=$@
echo “$line”
}
coproc tail -f /var/log/messages
while read line ; do
process_line “$line”
done <&${COPROC[0]}

“协进程”逐行输出/var/log/messages新增的行,前台程序逐行处理。

实际上,在bash 3中,在没有提供coproc的环境里,也可以使用这样的“思想”,实现“shell的多进程编程”。

3. 关联数组

bash支持的新“数据结构”,类似于Python的字典,PHP的关联数组。就是
p[name]=’hongchuan’
p[age]=28
p[site]=’http://www.bsdmap.com’

可以使用字符串作为数组的下标,引用值时${p[name]},${p[site]},${p[age]}。

使用“关链数组”需要事先声明:
declare -A p

4. 大小写转换

declare -l hostname
declare -u  MAC

声明变量hostname为小写,当执行hostname=”WWW.BSDMAP.COM”时,hostname的值为www.bsdmap.com。
声明变量MAC为大写,当MAC=”00:1b:2f:4c:19:7e”,MAC的值为 00:1B:2F:4C:19:7E。

5.  前置0

bash3中,为了产生0021这样的数,我是这么做的

for vlan in {1..10}; do
vlan_id=`printf %4d vlan|sed ‘s/ /0/g’`
……
done

bash4中,可以这样:
for vlan_id in {0001..10}; do
……
done

6. mapfile (readarray)

将文件装入数组
mapfile aa < log.txt
将文件log.txt以行为单位赋值给数组aa
callback() {
echo ${aa[@]}
}

mapfile -C callback -c1 aa < log.txt

help mapfile 更多详情。这个mapfile功能相当适用。

7. 新增两个重定向简写符

&>> 和 |&

&>> 等价于 >> file 2>&1

|&     等价于 2>&1 |

更多新特性,见官方手册。

 

 

有用的链接:

http://www.gnu.org/software/bash/
http://wiki.bash-hackers.org/bash4

http://www.gnu.org/software/bash/manual/bashref.html


6
十一 10

在脚本中使用ssh时的几个注意事项

1. 超时设置
-o ConnectTimeout=3

2. 重定项标准输入到/dev/null
-n
当使用这样的形式时 (使用 key 认证):

    while read line ; do
        ip=$(awk '{print $1}' < << $line )
        ssh -n -o ConnectTimeout=3 $i uptime
    done < file

假如此时不使用 -n ,则只有第一行会被处理。

3. 批处理模式,在脚本中使用再合适不过(使用 key 认证)
-o BatchMode=yes
当 key 认证不成功时,有可能会弹出“密码认识”,从而影响脚本运行下去,此时可以打开 BatchMode模式。

4. 遇到未知主机:

-o StrictHostKeyChecking=no

当遇到未知的主机公钥时,自动接受key。

5. 糟遇远程主机连接后无响应:

当设置了 BatchMode 时 ServerAliveInterval 默认被设置成 300 秒(服务端无数据传回的持续时间)。
ServerAliveCountMax相当于是重试的次数,比如下面的例子,15秒 x 3 = 45 秒,即当 45 秒后,真正超时断开。
TCPKeepAlive打开时,便于发现网络的断开。当网络故障(比如路由器坏掉)或者远端开机、死机时,连接会主动断开,否则的话,将会等待相当一段时间后才会断开。

-o ServerAliveInterval=15
-o ServerAliveCountMax=3
-o TCPKeepAlive=yes

需要注意的是,这里的超时、无响应,仅是 ssh或者sshd无影响,假如是在远程上执行程序,程序无响应,则不能处理此时的超时,解决方法见上一篇《在Shell中实现异步》。

 


6
十一 10

在Shell中实现异步

在shell脚本中,如何实现异步的超时设置功能?

关键部分的代码如下:

            scp ../local_hw_oob_init.sh $i: &>/dev/null
            ssh $i /root/local_hw_oob_init.sh &>/dev/null &
            SSHPID=$!
            { sleep 60 ; kill -9 $SSHPID ; } &
            KILLPID=$!
            wait $SSHPID
            if [ $? = 0 ] ; then
                kill -9 $KILLPID
                echo -n "SSH_OK,"
            else
                echo -n "SSH_KILLED,"
            fi

首先,将主任务 TASK1 放到后台,记录 TASK1_PID;然后立即在后台再运行第二个任务 { sleep 60 ; kill -9 $TASK1_PID ; } 到后台,然后启动一个 waith $TASK1_PID 的指令。

假如在 60 秒内,TASK1 还没有返回,就会被第二个后台的任务 kill 掉,此时,waith 收到 TASK1 的退出状态,并返回。
假如在 60 秒内,TASK1 返回,则wait之后,紧跟着 kill 掉第二个任务。


10
二 10

系统调用exec和fork

Exec 与 fork 是 UNIX 中的两个系统调用,UNIX 程序利用它们来创建新的进程。

由一个进程产生 (spawn) 另一个进程 ,可能是进程产生后用新进程取代它,即exec;或者如何需要保留这个进程,那就复制一个进程,即 fork 。

举个例子:Getty 进程监测一个串行端口 (tty),提供了一个 “login:” 提示符,当用户输入登录名回车之后,getty的任务就完成了;它执行 (exec) 了 login 命令,当 login 检测密码输入正确之后,它执行 (exec) 登录 shell 。一旦用户启动另一个程序,shell 程序就会派生 (fork) 自己,并且这个复本将执行 (exec) 用户所要运行的任何程序。


17
九 08

几个性能工具备忘

top:

* A: PID        = Process Id
* E: USER       = User Name
* H: PR         = Priority
* I: NI         = Nice value
* O: VIRT       = Virtual Image (kb)
* Q: RES        = Resident size (kb)
* T: SHR        = Shared Mem size (kb)
* W: S          = Process Status
* K: %CPU       = CPU usage
* N: %MEM       = Memory usage (RES)
* M: TIME+      = CPU Time, hundredths
b: PPID       = Parent Process Pid
c: RUSER      = Real user name
d: UID        = User Id
f: GROUP      = Group Name
g: TTY        = Controlling Tty
j: P          = Last used cpu (SMP)
p: SWAP       = Swapped size (kb)
l: TIME       = CPU Time
r: CODE       = Code size (kb)
s: DATA       = Data+Stack size (kb)
u: nFLT       = Page Fault count
v: nDRT       = Dirty Pages count
y: WCHAN      = Sleeping in Function
z: Flags      = Task Flags <sched.h>
* X: COMMAND    = Command name/line

Flags field:
0×00000001  PF_ALIGNWARN
0×00000002  PF_STARTING
0×00000004  PF_EXITING
0×00000040  PF_FORKNOEXEC
0×00000100  PF_SUPERPRIV
0×00000200  PF_DUMPCORE
0×00000400  PF_SIGNALED
0×00000800  PF_MEMALLOC
0×00002000  PF_FREE_PAGES (2.5)
0×00008000  debug flag (2.5)
0×00024000  special threads (2.5)
0x001D0000  special states (2.5)
0×00100000  PF_USEDFPU (thru 2.4)

进程的优先级和nice级别
进程优先级是一个决定进程被CPU执行优先顺序的参数,内核会根据需要调整这个值。Nice值是一个对优先权的限制。进程优先级的值不能低于nice值。(nice值越低优先级越高)
进程优先级是无法去手动改变的,只有通过改变nice值去间接的调整进程优先级。如果一个进程运行的太慢了,你可以通过指定一个较低的nice值去为它分配更多的CPU资源。当然,这意味着其他的一些进程将被分配更少的CPU资源,运行更慢一些。Linux支持nice值的范围是19(低优先级)到-20(高优先级),默认的值是0。如果需要改变一个进程的nice值为负数(高优先级),必须使用su命令登陆到root用户。下面是一些调整nice值的命令示例,
以nice值-5开始程序xyz
#nice –n -5 xyz

改变已经运行的程序的nice值
#renice level pid

将pid为2500的进程的nice值改为10
#renice 10 2500

vmstat:

·process(procs)
r:等待运行时间的进程数量
b:处在不可中断睡眠状态的进程
w:被交换出去但是仍然可以运行的进程,这个值是计算出来的
·memoryswpd:虚拟内存的数量
free:空闲内存的数量
buff:用做缓冲区的内存数量
·swap
si:从硬盘交换来的数量
so:交换到硬盘去的数量
·IO
bi:向一个块设备输出的块数量
bo:从一个块设备接受的块数量
·system
in:每秒发生的中断数量, 包括时钟
cs:每秒发生的context switches的数量
·cpu(整个cpu运行时间的百分比)
us:非内核代码运行的时间(用户时间,包括nice时间)
sy:内核代码运行的时间(系统时间)
id:空闲时间,在Linux 2.5.41之前的内核版本中,这个值包括I/O等待时间;
wa:等待I/O操作的时间,在Linux 2.5.41之前的内核版本中这个值为0

iostat:

%user:user level(应用)的CPU占用率情况
%nice:加入nice优先级的user level的CPU占用率情况
%sys:system level(内核)的CPU占用情况
%idle:空闲的CPU资源情况

Device:块设备名
Tps:设备每秒进行传输的数量(每秒的I/O请求)。多个单独的I/O请求可以被组成一个传输操作,因为一个传输操作可以是不同的容量。
Blk_read/s, Blk_wrtn/s:该设备每秒读写的块的数量。块可能为不同的容量。
Blk_read, Blk_wrtn:自系统启动以来读写的块设备的总量。

块可能为不同的容量。块的大小一般为1024、2048、4048byte。可通过tune2fs或dumpe2fs获得:
# tune2fs -l /dev/hda1|grep ‘Block size’
Block size:               4096
# dumpe2fs -h /dev/hda1|grep ‘Block size’
dumpe2fs 1.35 (28-Feb-2004)
Block size:               4096


11
七 08

shell中的判断

[ -f $file ]
像这们的句子,应该写成
[ -f "${file}" ] 这样可以
第1:避免变量file里包含特殊符号的情况。(当然这样也不是万能的)
第2:万一还有一个变量f,那么$file就会出现异常。

2010-02-01
apachectl 脚本中判断变量不为空:
$ULIMIT_MAX_FILES=”ulimit -S -n `ulimit -H -n`”
if [ "x$ULIMIT_MAX_FILES" != "x" ] ; then
    $ULIMIT_MAX_FILES
fi


10
七 08

BASH中字符串的处理

$x=abcd

[得到长度]

方法1:
$expr length $x
4

方法2:
$echo ${#x}
4

方法3:
$expr “$x” : “.*”    #expr的手册信息
4           #STRING : REGEXP anchored pattern match of REGEXP in STRIN

[查找子串]

$expr index $x “b”
2
$expr index $x “a”
1

[得到子字符串]

方法1:
#expr startpos length
$expr substr “$x” 1 3
abc
$expr substr “$x” 1 5
abcd
$expr substr “$x” 2 5
bcd

方法2:
#${x:pos:lenght}
$echo ${x:1}
bcd
$echo ${x:2}
cd
$echo ${x:0}
abcd
$echo ${x:0:1}
a

[匹配正则表达式]

[打印匹配长度]
$expr match $x “.”
1
$expr match $x “abc”
3
$expr match $x “bc”
0

[字符串的掐头去尾]

$x=aabbaarealwwvvww
$echo “${x%w*w}”
aabbaarealwwvv
$echo “${x%%w*w}”
aabbaareal
$echo “${x##a*a}”
lwwvvww
$echo “${x#a*a}”
bbaarealwwvvww

其中 , # 表示掐头, 因为键盘上 # 在 $ 的左面。
其中 , % 表示%, 因为键盘上 % 在 $ 的右面。
单个的表示最小匹配,双个表示最大匹配。
也就是说,当匹配的有多种方案的时候,选择匹配的最大长度还是最小长度。

[字符串的替换]

$x=abcdabcd
$echo ${x/a/b} # 只替换一个
bbcdabcd
$echo ${x//a/b} # 替换所有
bbcdbbcd


10
七 08

SHELL程序的不同执行方式

在当前shell环境运行:继承并影响当前环境。
. a.sh
source a.sh
实际上,”.”号与source的效果是一样的。
在当前shell运行时,需要注意,shell程序会影响、改变当前shell的环境。假如a.sh中有exit指令,那么用户将退出shell登录。

启动新的shell执行:只继承export输入的变量,并切不影响父进程的环境。exit指令只是退出新启动的shell。
bash a.sh
bash <a.sh
chmod+x a.sh
./a.sh

在( ) 中运行:executed in a subshell environment

也是在新的进程中运行。但是继承关系有点复杂,实验如下:

####START####
$su -
#chmod +x a.sh
#cat a.sh
echo $a
exit
#a=FreeBSD
#(./a.sh)

#(source a.sh)
FreeBSD
#(. a.sh)
FreeBSD
####END####

a.sh中的exit均没有影响到当前shell,但是却继承了当前shell的变量,但是改变a的操作却不能影响当前shell下a的值。

另外:
exec ./a.sh
关于exec:
exec: exec [-cl] [-a name] file [redirection ...]
Exec FILE, replacing this shell with the specified program.
If FILE is not specified, the redirections take effect in this
shell. If the first argument is `-l’, then place a dash in the
zeroth arg passed to FILE, as login does. If the `-c’option
is supplied, FILE is executed with a null environment. The `-a’
option means to make set argv[0] of the executed process to NAME.
If the file cannot be executed and the shell is not interactive,
then the shell exits, unless the shell option `execfail’is set.

man bash

Compound Commands
A compound command is one of the following:

(list) list  is  executed in a subshell environment (see COMMAND EXECUTION ENVIRONMENT below).  Variable assignments and builtin commands that affect the shell’s environment do not remain in effect after the command completes.  The return status is the exit status  of list.

{ list; }
list  is simply executed in the current shell environment.  list must be terminated with a newline or semicolon.  This is known as a group command.  The return status is the exit status of list.  Note that unlike the metacharacters ( and ), { and } are reserved words and must occur where a reserved word is permitted to be recognized.  Since they do not cause a word break, they must be sep-arated from list by whitespace.
Command Substitution
Command substitution allows the output of a command to replace the command name.  There are two forms:

$(command)
or
‘command‘

Bash performs the expansion by executing command and replacing the command substitution with the standard output of the command, with any trailing  newlines  deleted.  Embedded newlines are not deleted, but they may be removed during word splitting.  The command substitution $(cat file) can be replaced by the equivalent but faster $(< file).

When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, ‘, or \.  The first backquote not preceded by a backslash terminates the command substitution.  When using the $(command) form, all characters between the parentheses make up the command; none are treated specially.

Command substitutions may be nested.  To nest when using the backquoted form, escape the inner backquotes with backslashes.

If the substitution appears within double quotes, word splitting and pathname expansion are not performed on the results.

COMMAND EXECUTION ENVIRONMENT
The shell has an execution environment, which consists of the following:

·      open files inherited by the shell at invocation, as modified by redirections supplied to the exec builtin

·      the current working directory as set by cd, pushd, or popd, or inherited by the shell at invocation

·      the file creation mode mask as set by umask or inherited from the shell’s parent

·      current traps set by trap

·      shell parameters that are set by variable assignment or with set or inherited from the shell’s parent in the environment

·      shell functions defined during execution or inherited from the shell’s parent in the environment

·      options enabled at invocation (either by default or with command-line arguments) or by set

·      options enabled by shopt

·      shell aliases defined with alias

·      various process IDs, including those of background jobs, the value of $$, and the value of $PPID

When a simple command other than a builtin or shell function is to be executed, it is invoked in a separate  execution  environment  that consists of the following.  Unless otherwise noted, the values are inherited from the shell.

·      the shell’s open files, plus any modifications and additions specified by redirections to the command

·      the current working directory

·      the file creation mode mask

·      shell variables and functions marked for export, along with variables exported for the command, passed in the environment

·      traps caught by the shell are reset to the values inherited from the shell’s parent, and traps ignored by the shell are ignored

A command invoked in this separate environment cannot affect the shell’s execution environment.

Command substitution, commands grouped with parentheses, and asynchronous commands are invoked in a subshell environment that is a duplicate of the shell environment, except that traps caught by the shell are reset to the values that the shell inherited from its parent  at invocation.   Builtin  commands  that are invoked as part of a pipeline are also executed in a subshell environment.  Changes made to the subshell environment cannot affect the shell’s execution environment.

If a command is followed by a & and job control is not active, the default standard input for the command is the  empty  file  /dev/null. Otherwise, the invoked command inherits the file descriptors of the calling shell as modified by redirections.


10
七 08

BASH多进程并行处理的方法实现

#!/bin/bash

SEND_THREAD_NUM=13
tmp_fifofile=”/tmp/$$.fifo” # 脚本运行的当前进程ID号作为文件名
mkfifo “$tmp_fifofile” # 新建一个随机fifo管道文件
exec 6<>”$tmp_fifofile” # 定义文件描述符6指向这个fifo管道文件
rm $tmp_fifofile
for ((i=0;i<$SEND_THREAD_NUM;i++));do
echo # for循环 往 fifo管道文件中写入13个空行
done >&6

for i in `seq 100`;do # 100 次 for 循环 开始
read -u6 # 从文件描述符6中读取行(实际指向fifo管道)

{
echo $i # 打印 i
sleep 3 # 暂停3秒
echo >&6 # 再次往fifo管道文件中写入一个空行。
} &

# {} 这部分语句被放入后台作为一个子进程执行,所以不必每次等待3秒后执行
#下一个,这部分的echo $i几乎是同时完成的,当fifo中13个空行读完后 for循环
# 继续等待 read 中读取fifo数据,当后台的13个子进程等待3秒后,按次序
# 排队往fifo输入空行,这样fifo中又有了数据,for语句继续执行

pid=$! #打印最后一个进入后台的子进程id
echo $pid

done
wait
exec 6>&- #删除文件描述符6

exit 0


1
七 08

在history命令中显示时间

FreeBSD 6.1上的csh,默认就是开启了这个功能的。
Linux上的BASH默认没有开启这个功能,开启办法是:设置环境变量HISTTIMEFORMAT,设备方法参照strftime的格式(man 3 strftime查看详细信息)。不过这个功能只有在BASH3.0以上的版本中才能使用。原文是这么写的:

New HISTTIMEFORMAT variable; value is a format string to pass to strftime(3). If set and not null, the `history’builtin prints out timestamp information according to the specified format when displaying history entries. If set, bash tells the history library to write out timestamp information when the history file is written.

比如,在~/.bash_profile里添加如下一行:
export HISTTIMEFORMAT=”%F %T ”
然后再使用history的时候,就会显示时间信息了。


26
六 08

在BASH中进行数学运算

以前只知道expr,今天发现了BASH内置的let:
let: let arg [arg ...]
Each ARG is an arithmetic expression to be evaluated.  Evaluation
is done in fixed-width integers with no check for overflow, though
division by 0 is trapped and flagged as an error.  The following
list of operators is grouped into levels of equal-precedence operators.
The levels are listed in order of decreasing precedence.

id++, id–      variable post-increment, post-decrement
++id, –id      variable pre-increment, pre-decrement
-, +            unary minus, plus
!, ~            logical and bitwise negation
**              exponentiation
*, /, %         multiplication, division, remainder
+, -            addition, subtraction
<<, >>          left and right bitwise shifts
<=, >=, <, >    comparison
==, !=          equality, inequality
&               bitwise AND
^               bitwise XOR
|               bitwise OR
&&              logical AND
||              logical OR
expr ? expr : expr
conditional operator
=, *=, /=, %=,
+=, -=, <<=, >>=,
&=, ^=, |=      assignment

Shell variables are allowed as operands.  The name of the variable
is replaced by its value (coerced to a fixed-width integer) within
an expression.  The variable need not have its integer attribute
turned on to be used in an expression.

Operators are evaluated in order of precedence.  Sub-expressions in
parentheses are evaluated first and may override the precedence
rules above.

If the last ARG evaluates to 0, let returns 1; 0 is returned
otherwise.

注:是“脚本”,不是“角本”。

2008-07-02

今天又有新的发现:

(( … )): (( expression ))
The EXPRESSION is evaluated according to the rules for arithmetic
evaluation.  Equivalent to “let EXPRESSION”.

$a=1
$(( a++ ))
$echo $a
2

2011-07-23
一个有意思的用法:
$ echo $((2#11111111))
255
二进制11111111的值(十进制)是多少?


26
六 08

对软链接的认识(bash中)

以下认知均指在BASH中

1. 软链接是个文件
2. 软链接可以指向文件,也可以指向目录。
3. 当一个软链接以”/”结尾时,BASH才会认为软链接指向的是目录。否帖BASH认为是文件。例如:
  $ls -l
  lrwxrwxrwx 1 root root 11 Jun 26 10:47 logs -> /data/logs/
  当删除logs时,应使用 rm logs 而不是 rm logs/(这有点费话)。

  我要说的主要问题是这儿:
  $find ./logs -type f
  输出为空,而
  $find ./logs/ -type f
  会输出/data/logs下的文件。


12
五 08

BASH中使用数组

Bash中还可以使用数组变量,其赋值有两种:

(1) name = (value1 … valuen) 此时下标从0开始
(2) name[index] = value

数组下标的范围没有任何限制,同时也不必使用连续的分量.

———————————————————-

$ A=(a b c def)
=========================================

$ echo ${A[@]} //取全部元素
a b c def
========================================
$ echo ${A[0]} //取第一个元素
a
========================================
//取得数组元素的个数
$ echo ${#A[@]}
4
$ echo ${#A
}
4
$ echo ${#A[3]} //取得元素3的长度
$
========================================

$ A[3]=yaoshuyin //将第三个元素重新赋值
$ echo ${A[@]}
a b c yaoshuyin

=======================================
//清除变量
$ unset A
$ echo ${A[@]}
$

=======================================

//清空变量,即将值变为空
$ A=
$ echo ${A[@]}
$
=======================================

A=B
B=C
unset $A 事实上所取消的变量是 B 而不是 A
=================示例 while循环=============

#建立数组
arrSource=(“arrJobs.php” “arrSubHangye.php” “arrFirst.php” )

arrDest=(“buildhr” \
“buildtrain/htdocs” \
“bankhr” \
“healthr” \
“elehr” \
)

#取数组无元素个数
lenArrSource=${#arrSource
}
lenArrDest=${#arrDest
}
#循环列出数组元素
i=0
while [ $i -lt $lenArrSource ]
do
echo ${arrSource[$i]}
let i++
done
i=0
while [ $i -lt $lenArrDest ]
do

echo ${arrDest[$i]}
let i++
done
=======================示例: for循环=========

#源文件
arrSource=(“/home/800hr/htdocs/login_jump.php”)

#目标网站
arrDest=(ithr elehr buildhr bankhr healthr ctvhr chenhr mechr clothr cneduhr 56hr tourhr foodhr greenhr cnlawhr waimaohr)

for outer in ${arrSource
} #${arrSource
} 是数组中的所有元素
do
for inner in ${arrDest
}
do
echo “ln -s $outer /home/${inner}/campus/”
done
done


6
十二 07

Shell产生随机数

BASH Shell中有一个用于生成随机数的变量:RANDOM

这个变量的值是不断变化的,每次echo $RANDOM都会得到不同的值,在shell角本中可以做为随机数使用。

从别人的脚本里得到的一个获得随机数的方法:
rand() {
dd if=/dev/urandom bs=1 count=4 2>/dev/null | od -t u4 | awk ‘NR=1{print $2}’
}