shell脚本实例备忘

将一些练习题以及我自己实际写过的shell脚本记录于此,供学习查询。

  • 用户输入y或Y结束

while方式
#!/bin/bash
read -p "input you choice : " c
while [ "$c" != "Y" -a "$c" != "y" ]
do
    read -p "input you choice : " c
done
echo "Ok!"

until方式
#!/bin/bash
until [ "$c" == "Y" -o "$c" == "y" ]
do
    read -p "input your choice : " c
done
echo "done!"


  • case、函数、函数参数使用方法

#!/bin/bash
function print()
{
    echo "Your choice is $1"
}
case $1 in
    "one")
    #echo "one"
    print 1
    ;;
    "two")
    #echo "two"
    print 2 
    ;;
    "three")
    #echo "othre"
    print 3 
    ;;
    *)
    echo "Usage $0 {one|two|three}"
    ;;
esac


  • shell脚本中执行命令的方法

#!/bin/bash
str=$(whoami)    #或者:str=`whoami`(这里的引号为反引号——ESC下面那个键)
echo $str


  • shell脚本中for的使用方法

循环读取字符串中的每一个子串(以空格隔开)
#!/bin/bash
string="Waiting for a while"
for str in ${string}
do
    echo $str
done

循环读取字符串中的每一个子串(以空格隔开)
#!/bin/bash
for str in "Waiting for a while"
do
    echo $str
done

循环读取ls命令返回结果的每一个
#!/bin/bash
for str in `ls`
do
    echo $str
done

循环次数的例子,for(())是bash支持的
#!/bin/bash
for ((i=0; i<10; i++))    #或者:for i in {1..10}
do
    echo $i
done


  • dirname 命令与脚本语句$(dirname "${0}")

显示指定路径除了最后的文件名或者目录名之外的路径前缀,即截取给定路径的目录部分。例如:dirname /usr/bin/sort 得到/usr/bin。

在shell脚本中经常看到这样的语句:$(dirname "${0}")
说明:${0}表示当前脚本的第一个参数,即程序的完整路径,再执行dirname命令,则取得当前脚本所在的目录。

还有语句:cd $(dirname "$0") || exit 1 
说明:$(dirname "$0")表示当前脚本所在的目录,cd即进入脚本所在目录,失败则exit 1(退出)。

还有常用的获取当前脚本文件所在目录的方式:

THIS_DIR=$(cd "$(dirname $0)"; pwd)

或者是:

THIS_DIR=$(readlink -f "$(dirname "${0}")")

  • grep妙用
今天在shell脚本中看到这样一条语句:

NUM_JOBS="$(grep -c "^processor" /proc/cpuinfo)"

文件/proc/cpuinfo是cpu的信息,grep -c只统计查询结果的行数但是不输出,正则表达式"^processor"表示以processor开始的行,查看/proc/cpuinfo文件可以看出processor开始的行是cpu的第几个核心的信息。综上可知上面的shell语句就是统计了当前机器的cpu核心数目。


  • 判断字符串是否是数

function isDigit()
{		
	if [ $# == 1 ];then
		if [ `echo $1 | grep -P  "^\d+$" | wc -l` == 1 ];then
			return 0;
		fi
	fi
	return 1;
}

isDigit '111'
echo $?
isDigit 'ass'
echo $?

  • apache httpd自动编译生成的小脚本
脚本功能很简单,先判断当前目录中是否有Makefile文件,有则执行make进行编译生成,否则执行./configure(默认该文件存在,可以加上一条判断语句)生成Makefile文件,再进行判断和执行,过程中用MAKE_RES记录make执行的返回值,最终打印出该值。

#!/bin/bash

MAKE_RES=255	# 记录make的返回值,默认失败

if [ -f Makefile ];then		# 测试Makefile文件是否存在
  make				# 执行make
  MAKE_RES=$?			# 保存make的返回值
else				# 如果Makefile文件不存在,则执行configure
  ./configure --with-included-apr --with-pcr
  if [ -f Makefile ];then	# 判断是否生成了Makefile文件
    make
    MAKE_RES=$?
  else
    echo "./configure failed!"
  fi
fi

echo "Make result : "${MAKE_RES}	# 输出make的返回值(0表示成功,其他表示失败)

  • 判断用户输入的字符串是否为“Yes”或“No”(包含各种大小写字母组合)
case "$OPT" in
	[Oo][Nn]) CMD='YES';;
	[Oo][Ff][Ff]) CMD='NO';;
	*)
		echo '选项格式错误! 请用on 或off 来切换匿名登录的开关。'
		exit 1
		;;
esac

  • for循环一例
#! /bin/bash

DIR="/var"
cd ${DIR}
for f in $(ls ${DIR})
do
    [ -d $f ] && du -s $f
done
该脚本用来列出/var目录下各子目录占用磁盘空间的大小。

  • 脚本中用sudo执行命令,怎样自动输入密码,以免脚本执行中断等待用户输入密码
echo "password" | sudo -S netstat -tlnp      
The -S (stdin) option causes sudo to read the password from the standard input instead of the terminal device.

  •  系统/etc/profile 中的一段代码,可以学习借鉴
<span style="font-size:12px;">if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do   #×××
    if [ -r $i ]; then
      . $i
    fi
  done
  unset i
fi</span>
经常会有这样的需求:获取某个路径下的所有文件或者某些匹配的文件,然后做某种操作。以前的做法是先用find或者ls+grep的方式获取结果,然后再对结果进行循环操作,例如:result=$(find /etc/profile.d/ -name *.sh)  或者 result=$(ls /etc/profile.d/ | grep ".sh$")。
今天开了一下/etc/下的配置文件profile,看到如上的一段代码,其中#×××的语句值得借鉴,根本不需要查找!!!


  •  一个简单的例子,包含我写脚本的基本框架,以后可以复用
#! /bin/bash
###############################################################################
# author: andy <44452114@qq.com>
# date: 04/24/2014
# descrp: 脚本功能为列出给定目录中所有的文件和目录,通过参数形式给定需要查询
#         的目录。运行方式如下:
#             $ ./list_dir.sh /home/andy
#
###############################################################################

# 判断输入参数是否合法
if [[ $# < 1 ]]; then
	echo "[Error] Too few parameters!"
	exit 1
fi

# 获得输入的参数
dir=$1
if [ ! -d $dir ]; then
	echo "[Error] The path you give($dir) not exist!"
	exit 2
fi

# 程序功能实现
list=$(ls $dir)
for item in $list
do
	echo "item : $item"
done

# 结束提示
echo "Ok!"


  •  对目录中所有文件求md5值并输出到文件
sudo find . -type f -print0 | xargs -0 md5sum | grep -v "\./md5sum.txt" > md5sum.txt

  •  命名临时文件
TMP_file="/tmp/tmp.$$"
$$是Script 的进程编号,利用$$组成临时文件名,这样,可避免不同的Script 开启重复的临时文件。

  •  一个例子
维护debian源码包时,需要获取源码包需要的编译依赖。要想知道你的软件在编译的时候需要用到哪一个软件包,可以通过下面的方法,在源码根目录运行: 
  strace -f -o /tmp/log ./configure 
部分log文件文件如下:
32171 mmap2(NULL, 126192, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb76e0000
32171 close(3)                          = 0
32171 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
32171 open("/lib/i386-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
32171 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\320\n\0\0004\0\0\0"..., 512) = 512
32171 fstat64(3, {st_mode=S_IFREG|0644, st_size=13856, ...}) = 0
32171 mmap2(NULL, 16512, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb76db000
32171 mmap2(0xb76de000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0xb76de000
32171 close(3)                          = 0
32171 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
32171 open("/lib/i386-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
32171 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\0F\0\0004\0\0\0"..., 512) = 512
32171 fstat64(3, {st_mode=S_IFREG|0644, st_size=280108, ...}) = 0
在使用下面的脚本分析,提取出依赖的软件包及版本,脚本如下(重要的地方加了注释):
for x in `dpkg -S $(grep open ./log|\
		perl -pe 's!.* open\(\"([^\"]*).*!$1!' |\
		grep "^/"| sort | uniq|\
		grep -v "^\(/tmp\|/dev\|/proc\)" ) 2>/dev/null|\
		cut -f1 -d":"| sort | uniq`; \
do
   echo -n "$x (>=" `dpkg -s $x|grep ^Version|cut -f2 -d":"` "), "; 
done 

# 注释说明
# 1行:找到含有open的行;
# 2行:perl -pe 's!!!'或者perl -pe 's///',替换字符串。这里实际上是为了得到$1,例如:
#      上面log的第4行,会提取得到:/lib/i386-linux-gnu/libdl.so.2,注意读一下其中的正则匹配,
#      匹配open后面“”中的内容保存在$1;
# 3行:提取/开头的行;
# 4行:去掉/tmp,/dev,/proc开始的行,即不处理/tmp,/dev,/proc开头的文件。注意这里有grep使用
#      的技巧——查询多个字符串匹配:grep "\(aaa\|bbb\))
# 另外,dpkg -S 查询某个文件属于哪个debian包,dpkg -s 查询debian包的详细信息。




  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值