echo
date +%T 以格式化输出当前时间
示例
#!/bin/bash
# This is the first Bash shell program
# Scriptname: greetings.sh
echo
echo -e "Hello $LOGNAME, \c"
echo "it's nice talking to you."
echo -n "Your present working directory is: "
pwd # Show the name of present directory
echo
echo -e "The time is `date +%T`!. \nBye"
echo
时间同步shell脚本
#!/bin/bash
## Script Name:/etc/cron.daily/ntpdate
# 使用NTP的客户端命令ntpdate与远程NTP服务器进行同步
# 也可以用局域网内的NTP服务器替换 pool.ntp.org
/usr/sbin/ntpdate -s pool.ntp.org
# 更改硬件时钟时都会记录在/etc/adjtime文件中
# 使hwclock根据先前的记录来估算硬件时钟的偏差,
# 并用来校正目前的硬件时钟
/sbin/hwclock --adjust
# 将系统时钟同步到硬件时钟
/sbin/hwclock –systohc
示例
#!/bin/bash
# This is the first Bash shell program
# Scriptname: greetings.sh
set -x ### Turn ON debug mode ###
echo
echo -e "Hello $LOGNAME, \c"
echo "it's nice talking to you."
echo -n "Your present working directory is: "
pwd # Show the name of present directory
echo
set +x ### Turn OFF debug mode ###
echo -e "The time is `date +%T`!. \nBye"
echo
通过 str2 的值来引用 str1 的值
错误示例
str1="Hello World"
str2=str1
echo $str2
正确示例
str1="Hello World"
str2=str1
newstr=${!str2}
echo $newstr
Hello World
或
echo ${!str2}
Hello World
或
eval newstr=\$$str2
echo $newstr
Hello World
或
eval echo \$$str2
Hello World
x=”CENTOS”
通过 x 的值来引用 CENTOS_URL 的值
# bash2.0以上才支持
newstr=${x}_URL
echo $newstr
CENTOS_URL
echo ${!newstr}
http://mirrors.163.com/centos/
或
eval newstr=\$${x}_URL
echo $newstr
或
eval echo \$${x}_URL
eval arg1 [arg2] … [argN]
* 对参数进行两次扫描和替换
* 将所有的参数连接成一个表达式,并计算或执行该表达式
* 参数中的任何变量都将被展开
listpage="ls -l | more"
eval $listpage
eval $(ssh-agent)
eval newstr=\$$str2
eval echo \$${x}_URL
命令行参数相关
$* 获取当前shell脚本所有传参的参数,将所有位置参量看成一个字符串(以空格间隔),相当于""$1$2$3$4$5 。
$@ 将每个位置参量看成单独的字符串(以空格间隔)"$!" "$2" "...."。
"$*" 将所有位置参量看成一个字符串(以$IFS间隔)。
"$@" 将每个位置参量看成单独的字符串(以空格间隔) 。
$0 命令行上输入的Shell程序名。
$# 表示命令行上参数的个数。
进程状态相关
$? 表示上一条命令执行后的返回值
$$ 当前进程的进程号
$! 显示运行在后台的最后一个作业的 PID
$_ 在此之前执行的命令或脚本的最后一个参数
示例
经常与循环结构语句一起使用,以便遍历每一个位置参数
#!/bin/sh
# ScriptName: pp_shift.sh
# To test Positional Parameters & Shift.
echo "The script name is : $0"
echo '$1'=$1,'$2'=$2,'$3'=$3,'$4'=$4 -- '$#'="$#"
echo '$@': "$@"
shift # 向左移动所有的位置参数1次
echo '$1'=$1,'$2'=$2,'$3'=$3,'$4'=$4 -- '$#'="$#"
echo '$@': "$@"
shift 2 # 向左移动所有的位置参数2次
echo '$1'=$1,'$2'=$2,'$3'=$3,'$4'=$4 -- '$#'="$#"
echo '$@': "$@"
$ ./pp_shift.sh 1 b 3 d 4 f
$ echo $$ # 显示当前进程的 PID
9245
$ echo $? # 显示在此之前执行的命令的返回值
0
$ bash # 调用子Shell
$ echo $$ # 显示当前进程的 PID
9474
$ exit 1 # 指定返回值并返回父Shell
$ echo $? # 显示上一个Shell/脚本的返回值
1
$ list # 执行不存在的命令
bash: list: command not found
$ echo $?
127
$ touch bbb.sh
$ ./bbb.sh # 执行不具有执行权限的命令
bash: ./bbb.sh: Permission denied
$ echo $?
126
:将命令执行的结果输出给变量 #!/bin/bash
# This script is to test the usage of read
# Scriptname: ex4read.sh
echo "=== examples for testing read ==="
echo -e "What is your name? \c"
read name
echo "Hello $name"
echo
echo -n "Where do you work? "
read
echo "I guess $REPLY keeps you busy!"
echo
read -p "Enter your job title: "
echo "I thought you might be an $REPLY."
echo
echo "=== End of the script ==="
[lrj@centos1 ~]$ myname=Osmond
[lrj@centos1 ~]$ echo $myname
Osmond
[lrj@centos1 ~]$ readonly myname
[lrj@centos1 ~]$ unset myname
-bash: unset: myname: cannot unset: readonly variable
[lrj@centos1 ~]$ myname="Osmond Liang"
-bash: myname: readonly variable
$ var=test
$ echo $var
test
$ echo $varAA
$varAA
$ echo ${var}AA
testAA
$ ls
a b c
$ echo $(ls)
a b c
$ echo `ls`
a b c
let 内置命令用于算术运算
num2=1; echo $num2
let num2=4+1; echo $num2
let num2=$num2+1; echo $num2
如果变量的值是字符串,则进行算术运算时设为 0
let num2=4 + 1
let "num2=4 + 1" # 用引号忽略空格的特殊含义
表达式中的运算可以是算术运算,比较运算,字符串运算和逻辑运算。
expr 5 % 3
expr 5 \* 3 # 乘法符号必须被转义
expr 2 + 5 \* 2 - 3 % 2
expr \( 2 + 5 \) \* 2 – 3 # 括号必须被转义
可以通过使用 bc 或 awk 工具来处理浮点数运算
n=$(echo "scale=3; 13/2" | bc )
echo $n
m=`awk 'BEGIN{x=2.45;y=3.123;printf "%.3f\n", x*y}'`
echo $m
使用 declare 声明或直接给变量名加下标来赋值
declare -a variable
variable=(item1 item2 item2 ... )
数组的引用
${variable[n]}
declare myname=osmond
declare –r myname=osmond
unset myname
declare myname=“Osmond Liang"
declare –x myname2=lrj
myname2=lrj
declare –x myname2
if expr1 # 如果 expr1 为真(返回值为0)
then # 那么
commands1 # 执行语句块 commands1
elif expr2 # 若 expr1 不真,而 expr2 为真
then # 那么
commands2 # 执行语句块 commands2
... ... # 可以有多个 elif 语句
else # else 最多只能有一个
commands4 # 执行语句块 commands4
fi # if 语句必须以单词 fi 终止
case expr in # expr 为表达式,关键词 in 不要忘!
pattern1) # 若 expr 与 pattern1 匹配,注意括号
commands1 # 执行语句块 commands1
;; # 跳出 case 结构
pattern2) # 若 expr 与 pattern2 匹配
commands2 # 执行语句块 commands2
;; # 跳出 case 结构
... ... # 可以有任意多个模式匹配
*) # 若 expr 与上面的模式都不匹配
commands # 执行语句块 commands
;; # 跳出 case 结构
esac # case 语句必须以 esac 终止
for variable in list
# 每一次循环,依次把列表 list 中的一个值赋给循环变量
do # 循环体开始的标志
commands # 循环变量每取一次值,循环体就执行一遍
done # 循环结束的标志,返回循环顶部
可以省略 in list ,省略时相当于 in “$@”
首先将 list 的 item1 赋给 variable
for ((expr1;expr2;expr3)) # 执行 expr1
do # 若 expr2的值为真时进入循环,否则退出 for循环
commands # 执行循环体,之后执行 expr3
done # 循环结束的标志,返回循环顶部
expr3 在每次执行循环体之后执行一次
首先执行 expr1
while expr # 执行 expr
do # 若expr的退出状态为0,进入循环,否则退出while
commands # 循环体
done # 循环结束标志,返回循环顶部
* While 和输入重定向
* 使用管道为 while 传递输入
until expr # 执行 expr
do # 若expr的退出状态非0,进入循环,否则退出until
commands # 循环体
done # 循环结束标志,返回循环顶部
将循环结果通过管道传递给其他命令处理(done |)
后台执行循环(done &)
select variable in list
do # 循环开始的标志
commands # 循环变量每取一次值,循环体就执行一遍
done # 循环结束的标志
./foo.txt 和 ./mydir 是脚本的处理对象,他们是不与任何选项相关的参数,在POSIX®标准中称其为“操作 对象/数”(operands)
按照Linux的命令行书写规范,如下命令行
也可以写成如下的等价形式
ARGS : 参数列表,省略时为 ”$@”
getopts c:zrv opt
getopts :c:zrv opt
getopts的执行过程
getopts的错误报告模式
while getopts OPTSTRING VARNAME
do
case $VARNAME in
…) ………… ;;
…) ………… ;;
:) ………… ;;
\?) ………… ;;
esac
done
示例1
#!/bin/bash
## filename : pp_parse_getopts_1.sh
while getopts "abc:def:ghi" flag
do
echo "$flag" $OPTIND $OPTARG
done
echo "Resetting"
OPTIND=1
while getopts "bc:def:ghi" flag
do
echo "$flag" $OPTIND $OPTARG
done
$ ./pp_parse_getopts_1.sh -a -bc foo -f "foo bar" -h –gde
$ ./pp_parse_getopts_1.sh -abf "foo bar" -h -gde –c
$ ./pp_parse_getopts_1.sh -abf “foo bar” -h –c -gde
示例2
#!/bin/bash
## filename : pp_parse_getopts_2.sh
while getopts ":abc:def:ghi" flag
do
echo "$flag" $OPTIND $OPTARG
done
echo "Resetting"
OPTIND=1
while getopts ":bc:def:ghi" flag
do
echo "$flag" $OPTIND $OPTARG
done
$ ./pp_parse_getopts_2.sh -a -bc foo -f "foo bar" -h -gde
$ ./pp_parse_getopts_2.sh -abf "foo bar" -h -gde –c
$ ./pp_parse_getopts_1.sh -abf “foo bar” -h –c -gde
* 示例3
#!/bin/bash
## filename : mybackup_getopts.sh
while getopts :zc:x:rv opt
do
case $opt in
c) ConfFile=$OPTARG ;;
x) ExcludeFile=$OPTARG ;;
z) Compress=true ;;
r) Recursive=true ;;
v) Verbose=true ;;
:)
echo "$0: Must supply an argument to -$OPTARG." >&2
exit 1
;;
\?) echo "Invalid option -$OPTARG ignored." >&2 ;;
esac
done
shift $((OPTIND-1)) ; echo $0 ; echo "$@"
示例4
#!/bin/bash
## filename : mybackup_getopts2.sh
while getopts :zc:x:rv opt
do
case $opt in
c) if [[ $OPTARG = -* ]]; then ((OPTIND--)) ; continue ; fi
ConfFile=$OPTARG ;;
x) ExcludeFile=$OPTARG ;;
z) Compress=true ;;
r) Recursive=true ;;
v) Verbose=true ;;
:)
echo "$0: Must supply an argument to -$OPTARG." >&2
exit 1
;;
\?) echo "Invalid option -$OPTARG ignored." >&2 ;;
esac
done
shift ((OPTIND-1)) ; echo $0 ; echo "$@"
函数的定义和调用
示例1
#!/bin/bash
## filename: all_in_one_backup_select.sh
### User define Function (UDF) ###
sql_bak () { echo "Running mysqldump tool..."; }
sync_bak () { echo "Running rsync tool..."; }
git_bak () { echo "Running gistore tool..."; }
tar_bak () { echo "Running tar tool..."; }
### Main script starts here ###
PS3="Please choose a backup tools : "
select s in mysqldump rsync gistore tar quit ; do
case $REPLY in
1) sql_bak ;;
2) sync_bak ;;
3) git_bak ;;
4) tar_bak ;;
5) exit ;;
esac
done
示例2
#!/bin/bash
## filename: /root/bin/my_backup_functions.sh
### User define Function (UDF) ###
sql_bak () { echo "Running mysqldump tool..."; }
sync_bak () { echo "Running rsync tool..."; }
git_bak () { echo "Running gistore tool..."; }
tar_bak () { echo "Running tar tool..."; }
示例3
#!/bin/bash
## filename: all_in_one_backup_select.sourcefunc.sh
source /root/bin/my_backup_functions.sh
### Main script starts here ###
PS3="Please choose a backup tools : "
select s in mysqldump rsync gistore tar quit ; do
case $REPLY in
1|[mM]ysqldump) sql_bak ;;
2|[rR]sync) sync_bak ;;
3|[gG]istore) git_bak ;;
4|[tT]ar) tar_bak ;;
5) exit ;;
esac
done
函数与位置参数
示例1
#!/bin/bash
## filename: pp_and_function.sh
echo "===Print positional parameters in main :"
echo "$0: $*"
pp1(){
echo 'f1--Print $* parameters in fun1 :' ; echo "$0: $*"
}
pp2(){
echo 'f2--Print $* parameters in fun1 :' ; echo "$0: $*"
pp1 1st 2nd 3th 4th 5th 6th 7th 8th 9th
echo 'f2--Print $* parameters in fun1 :' ; echo "$0: $*"
}
pp1 1 2 3 4 5 6 7 8 9
echo "===Print positional parameters in main :"
echo "$0: $*"
pp2 I II III IV V VI VII VIII IX
./pp_and_function.sh a b c d e f g h i
示例2
#!/bin/bash
## filename: function_max.sh
# User define Function (UDF)
usage () {
echo "List the MAX of the positive integers in command line. "
echo "Usage: `basename $0` [ ... ]"
exit
}
max () {
[[ -z $1 || -z $2 ]] && usage
largest=0
for i ; do ((i>largest)) && largest=$i ; done
}
### Main script starts here ###
max "$@"
echo "The largest of the numbers is $largest."
./function_max.sh 1 58 111 32768 66
由于largest变量在函数max内没有使用local声明,所以它是全局的
#!/bin/bash
## filename: function_max2.sh
# User define Function (UDF)
max2 () {
if [[ -z $1 || -z $2 ]] ; then
echo "Need 2 parameters to the function." ; exit
fi
[ $1 -eq $2 ] &&
{ echo "The two numbers are equal." ; exit ; }
(($1>$2)) && return $1 || return $2
}
### Main script starts here ###
read -p "Please input two integer numbers : " n1 n2
echo "n1=$n1 , n2=$n2“
max2 $n1 $n2
return_val=$?
echo "The larger of the two numbers is $return_val."
使用标准输出返回函数值
#!/bin/bash
## filename: function_to-upper.sh
# User define Function (UDF)
to_upper () {
local str="$@"
local output
output=$(tr '[a-z]' '[A-Z]'<<<"${str}")
echo $output
}
### Main script starts here ###
to_upper "This Is a TEST"
res=$(to_upper "$@")
echo "$res"
res=$(to_upper "$1")
[[ $res == "YES" ]] && echo "Continue..." || echo "Stop"
./function_to-upper.sh YES we are
./function_to-upper.sh No we are not
系统INIT 启动脚本的结构——/etc/rc.d/init.d/*