Linux中常用的shell脚本

Linux中常用的shell脚本

1、对于进程来说,查看其运行时的环境变量

cat /proc/$PID/environ

示例

#首先需要我们运行一个程序
# pgrep inotifywait
8977
# cat /proc/8977/environ
HOSTNAME=localhost.localdomainSELINUX_ROLE_REQUESTED=TERM=xterm-256colorSHELL=/bin/bashHISTSIZE=1000SSH_CLIENT=192.168.1.100 63684 22SELINUX_USE_CURRENT_RANGE=SSH_TTY=/dev/pts/0USER=rootLS_COLORS=rs=0:di=38;... %sG_BROKEN_FILENAMES=1_=/usr/local/bin/inotifywaitOLDPWD=/data
#一般返回的环境变量会有很多,我们采用换行方式查看会更直观

# cat /proc/8977/environ | tr '\0' '\n'
HOSTNAME=localhost.localdomain
SELINUX_ROLE_REQUESTED=
TERM=xterm-256color
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=192.168.1.100 63684 22
SELINUX_USE_CURRENT_RANGE=
SSH_TTY=/dev/pts/0
USER=root
....

2、获得字符串长度

# var=wahaha
# echo ${var}
wahaha
# echo ${#var}
6

3、识别当前使用的是哪种shell

echo $SHELL
/bin/bash

4、shell脚本检查是执行当前脚本的是否为root用户

# cat check_root.sh
#!/bin/bash
if [ $UID -ne 0 ]; then
    echo "Non root user. Please run as root."
else
    echo Root User
fi

5、修改bash提示字符串(username@hastname:~$)

#利用PS1环境变量来定制
# cat ~/.bashrc | grep PS1
PS1='${debian_chroot:+$($debian_chroot)}\u@\h:\w\$ '
# \u 用户名
# \h 主机名
# \w 当前工作目录

6、如何判断一个命令是否执行成功

当一个命令发生错误并退回时,他会返回一个非0的退出状态;
而当命令成功完成后,它会返回数字0.
退出状态可以从特殊变量 $? 中获得(在命令执行之后立刻运行 $? ,就可以打印出退出状态)
#!/bin/bash
CMD="commod"  #commod代表需要检测退出状态的命令
$CMD
if [ $? -eq 0 ];
then
  echo "$CMD executed succ"
else
  echo "$CMD excuted unsucc"
fi

7、shell中数组的定义与操作

#定义1
array_var=(1 2 3 4 5)
#定义2
array_var[0]="test"
array_var[1]="test1"
array_var[2]="test2"
array_var[3]="test3"
#打印特定索引数组元素
echo ${array_var[0]}
#以清单形式打印出数组中的所有值
echo ${array_var[*]}
test test1 test2 test3
#也可以
echo ${array_var[@]}
test test1 test2 test3
#输出数组元素个数
echo ${#array_var[*]}
4

8、按照指定格式打印系统当前时间

# date "+%Y%m%d"
20161029
# %a  星期  例,Sat
# %A  星期  例,Saturday
# %b  月    例,Nov
# %B  月    例,November
# %d  日   例,31
# %D  固定格式(mm/dd/yy)  例,10/18/10
# %y  年   例,16
# %Y  年   例,2016
# %I或%H 小时  例,08
# %M  分钟  例,30
# %S  秒   例,10
# %N  纳秒  例,694394444

9、shell函数参数传递

#!/bin/bash
func(){
  echo $1,$2  #访问参数1和参数2
  echo "$@"   #以列表方式一次性打印所有参数
  echo "$*"   #类似于$@,但是参数被作为单个实体
  return 0;   #返回值
}

# $1,  第一个参数
# $2,  第二个参数
# $n,  第n个参数
# "$@",   被扩展成"$1" "$2" "$3"等
# "$*",   被扩展成"$1c$2c$3" ,其中c是IFS的第一个字符
# "$@"要比"$*"用的多。由于"$*"将所有参数当做单个字符串,因此它很少被使用

10、利用子shell生成独立进程

# cat sub_shell.sh
#!/bin/bash
pwd;
(cd /bin; pwd);
pwd;
# ./sub_shell.sh
/root/shell
/bin
/root/shell

# 我们可以发现()中的子shell对于当前shell没有影响,它所有的改变仅限于()内部

11、运行命令直至成功

repeat(){
  while true
  do
    $@  && return
  done
}
# 原理:该函数通过$@接收传参。如果命令执行成功,则返回并退出循环,否则一直循环

# Tips:将该函数加入的shell的rc文件中,方便我们使用

# 示例:使用repeat()从网上下载一个文件,直至成功
repeat wget -c http://xxxx.com/example.tar.gz

12、删除多余的空行

# cat -s file >> newfile

13、文件查找

# find /home -name "*.txt"
# find . \( -name "*.txt" -o -name "*.pdf" \)
...

14、排序、去重

# 排序  sort
# 去重  uniq
sort file.txt | uniq
# cat check_sorted.sh
#!/bin/bash
# 功能:检查文件是否已经排序过
sort -C filename;
if [ $? -eq 0 ]
then
  echo Sorted
else
  echo Unsorted
fi

15、交互输出自动化实现

#!/bin/bash
# 文件名:enter.sh
read -p "Enter number:" no ;
read -p "Enter name" name ;
echo You have entered $no $name;
#利用echo -e来生成输入序列
echo -e "1\nhello\n" | ./enter.sh

16、利用并行进程加速命令执行

#!/bin/bash
PIDARRAY=()
for file in File1.ios File2.ios
do
  md5sum $file &
  PIDARRAY+=("$!")
done
wait ${PIDARRAY[@]}
# 原理:利用bash的操作符&,它使得shell将命令置于后台并继续执行脚本。使用 $! 来获得进程的PID(在bash中 $! 保存最近一个后台进程的PID)。将这些进程PID放入PIDARRAY数组中。使用wait命令等待这些进程执行完成。

17、查找并删除内容重复的文件

#创建测试文件testfile,testfile1,testfile2,newfile ;其中testfile1和testfile2都是testfile的副本

# echo "hello" >> testfile
# cp testfile testfile1
# cp testfile testfile2
# echo hello world >> newfile

# cat remove_duplicates.sh
#!/bin/bash

ls -lS --time-style=long-iso | awk 'BEGIN {
    getline; getline;
    name1=$8; size=$5;
}{
    name2=$8
    if(size==$5){
        "md5sum "name1 | getline; csum1=$1;
        "md5sum "name2 | getline; csum2=$1;
        if(csum1==csum2){
            print name1;
            print name2;
        }
    }
    size=$5;
    name1=name2;
}' | sort -u > duplicate_files

cat duplicate_files | xargs -I {} md5sum {} | sort | uniq -w 32 | awk '{print "^"$2"$" }' | sort -u > duplicate_sample

echo Removing...
comm duplicate_files duplicate_sample -2 -3 | tee /dev/stderr | xargs rm
rm -f duplicate_files duplicate_sample
echo Removed duplicates files successfully

# 执行脚本
# ./remove_duplicates.sh
Removing...
testfile
testfile1
Removed duplicates files successfully

# 如上testfile、testfile1、testfile2这三个相同内容的文件,只保留了testfile2.

# 脚本原理说明:
# ls -lS 将当前目录下的所有文件按照文件大小进行排序,并列出文件的详细信息
# awk命令的执行步骤:awk首先会执行BEGIN{}语句块,处理完{}中所有的命令后,在执行END{}语句块
# 在awk中,外部的命令的输出可以用这样的方式来读取,"cmd" | getline ,随后我们就可以用 $0 来获取命令的输出 ,在$1,$2,$3...$n 获取命令输出中的每一列
# BEGIN{}语句块中有两个getline;是因为 ls -lS --time-style=long-iso 命令的输出的第一行是文件的数量,所以我们直接跳过,来获取下一行数据
# comm 通常只接受排过序的文件。所以在之前需要使用 sort -u 进行排序
# tee 命令在这有一个妙用:它将文件名在传递给rm命令的同时,也起到了print的效果。tee将来自stdin的行写入文件,同事将其发送到stdout

18、解析文本中的电子邮件地址和URL

# 正则表达式
#   mail:[a-zA-Z0-9.]+@[a-zA-Z0-9.]+\.[a-zA-Z]{2,4}
#   URL: (http|https)://[a-zA-Z0-9.]+\.[a-zA-Z]{2,3}

# wget www.sina.com.cn/index.html

# 解析index.html中的email
# egrep -o "[a-zA-Z0-9.]+@[a-zA-Z0-9.]+\.[a-zA-Z]{2,4}" index.html
jubao@vip.sina.com
jubao@vip.sina.com

# 解析index.html中的URL
# egrep -o "(http|https)://[a-zA-Z0-9.]+\.[a-zA-Z]{2,3}" index.html
http://www.sina.com.cn
http://www.sina.com.cn
http://auto.sina.com.cn
http://www.sina.com.cn
...
http://hq.sinajs.cn
http://rm.sina.com.cn
http://d4.sina.com.cn
http://d1.sina.com.cn
http://i1.sinaimg.cn
http://news.sina.com.cn
http://login.sina.com.cn
http://login.sina.com.cn

19、以纯文本形式下载网页

lynx:是一款基于命令行的web浏览器。我们可以利用它获取纯文本形式的网页

命令:
# lynx -dump http://www.sina.com.cn
-dump 选项表示将网页内容以ASCII编码形式打印

另,lynx会将页面中所有的超链接(<a href="link">)作为文本的页脚,单独放置在标题为 References 的文本区域。如果我们需要匹配除某个页面中所有的超链接也可以使用该方法,也省的我们用正则匹配

20、列出网络上所有的活动主机

# cat ping.sh
#!/bin/bash
for ip in 192.168.1.{1..255};
do
    ping $ip -c 2 &> /dev/null;

    if [ $? -eq 0 ]
    then
        echo $ip is alive
    fi
done

# 并行ping
# cat ping_1.sh
#!/bin/bash
for ip in 192.168.1.{1..255};
do
    (
    ping $ip -c 2 &> /dev/null;

    if [ $? -eq 0 ]
    then
        echo $ip is alive
    fi
    )&
done
wait

# 将wait放在脚本最后,它就会一直等到所有的子脚本进程全部结束

21、网络上利用套接字进行快速文件复制

# 设置侦听套接字
nc -l 1234

# 在另一终端或主机中连接到该套接字
nc 127.0.0.1 1234
message_test

# 连接到套接字后就可以在终端中输入信息回车就会发送

# 文件复制
在接收端执行以下命令:
nc -l 1234 > destination_filename
在发送端执行下列命令:
nc 127.0.0.1 1234 < source_filename