shell

1. 基础

# shell的执行方式:
- 路径方式 :必须赋予权限
- source  立即执行,不需要权限
- bash 执行

新建一个文件,扩展名为sh(sh代表shell),输入一些代码:

#!/bin/bash
echo "Hello World !"#!” 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种Shell。

运行Shell脚本有两种方法。

1.作为可执行程序,将上面的代码保存为test.sh,并 cd 到相应目录:

chmod +x ./test.sh  #使脚本具有执行权限
./test.sh #执行脚本
注意,一定要写成./test.sh,而不是test.sh。

2.作为解释器参数,这种运行方式是,直接运行解释器,其参数就是shell脚本的文件名,如:

/bin/sh test.sh
/bin/php test.php
这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用。

下面的脚本使用 read 命令从 stdin 获取输入并赋值给 PERSON变量,最后在 stdout 上输出:

#!/bin/bash
 
echo "What is your name?"
read PERSON
echo "Hello, $PERSON"
运行脚本:

chmod +x ./test.sh
$./test.sh

# 配置只使用名称运行
export PATH=/opt/sahre:$PATH    #在PATH中添加目录/opt/share
export PATH=$PATH:/opt/share


export设置环境变量是暂时的,只在本次登录中有效,可修改如下文件来使命令长久有效。

1. 修改profile文件
#vi /etc/profile

在里面加入:

export PATH="$PATH:/opt/share"

这个在我们的机器上是大家共用的,建议不修改这个,只修改自己根路径下的。

2. 修改本id根路径下的.bashrc或.bash_profile或$HOME/.profile文件:
# vi /home/zhaodw/.bash_profile

在里面加入:

export PATH="$PATH:/opt/share"

source /home/zhaodw/.bash_profile
注意:
1、执行脚本时是在一个子shell环境运行的,脚本执行完后该子shell自动退出;
2、一个shell中的系统环境变量才会被复制到子shell中(用export定义的变量);
3、一个shell中的系统环境变量只对该shell或者它的子shell有效,该shell结束时变量消失(并不能返回到父shell中)。
4、不用export定义的变量只对该shell有效,对子shell也是无效的。

2. test语句

执行条件表达式

# 执行条件表达式并显示返回值。
[root@pc root]$ test ! "abc" == 123; echo $?
0

# 等价形式,注意:方括号 [ 后面的空格以及方括号 ] 前面的空格。

[root@pc root]$ [ ! "abc" == 123 ]; echo $?
0
# 支持正则的测试 [[      ]] 
[root@pc root]$ [[ ! "abc" == 123 ]]; echo $?
0

3. shell 语法

算符描述示例
文件比较运算符
-e filename如果 filename 存在,则为真[ -e /var/log/syslog ]
-d filename如果 filename 为目录,则为真[ -d /tmp/mydir ]
-f filename如果 filename 为常规文件,则为真[ -f /usr/bin/grep ]
-L filename如果 filename 为符号链接,则为真[ -L /usr/bin/grep ]
-r filename如果 filename 可读,则为真[ -r /var/log/syslog ]
-w filename如果 filename 可写,则为真[ -w /var/mytmp.txt ]
-x filename如果 filename 可执行,则为真[ -L /usr/bin/grep ]
filename1 -nt filename2如果 filename1 比 filename2 新,则为真[ /tmp/install/etc/services -nt /etc/services ]
filename1 -ot filename2如果 filename1 比 filename2 旧,则为真[ /boot/bzImage -ot arch/i386/boot/bzImage ]
字符串比较运算符 (请注意引号的使用,这是防止空格扰乱代码的好方法)
-z string如果 string 长度为零,则为真[ -z “$myvar” ]
-n string如果 string 长度非零,则为真[ -n “$myvar” ]
string1 = string2如果 string1 与 string2 相同,则为真[ “$myvar” = “one two three” ]
string1 != string2如果 string1 与 string2 不同,则为真[ “$myvar” != “one two three” ]
算术比较运算符
num1 -eq num2等于[ 3 -eq $mynum ]
num1 -ne num2不等于[ 3 -ne $mynum ]
num1 -lt num2小于[ 3 -lt $mynum ]
num1 -le num2小于或等于[ 3 -le $mynum ]
num1 -gt num2大于[ 3 -gt $mynum ]
num1 -ge num2大于或等于[ 3 -ge $mynum ]
#!/bin/bash

touch hello.txt
# 变量类型默认都是字符串类型,无法直接进行数值运算
echo "脚本主题: data本身就是复数" >> hello.txt

echo "========================= 特殊变量 $n $# $* $@ ========================="
echo "$HOME"
echo "$SHELL"
echo "$USER"
# $1 获取第一个参数,$2 获取第二个参数
echo "第一个爱妃是 $1, 可谓是倾国倾城"
# $# 获取入参个数
echo "此次入宫了 $# 个妃子"
# $* 代表所有参数,看作整体
echo "妃子名单*: $*"
# $@ 代表所有参数,区分对待
# shellcheck disable=SC2145
echo "妃子名单@: $@"
# $? 上一次命令的执行状态。0: 正确执行; 非0 : 执行发生错误(具体是哪个数,由命令自己决定)
echo " 上一次命令执行状态: $? "

echo "========================= 定义变量(随用随注销) ========================="
echo "A=1, 等号两边不能有空格"
echo "变量名可以由字母、数字和下划线组成,但是不能以数字开头"
echo "变量默认都是以字符串类型,无法直接进行数值运算"
echo "变量的值如果有空格,需要使用双引号或单引号括起来"
Z=1
echo "$A的值是: $Z"

echo "========================= 运算符 ========================="
echo "一共有三种方式,推荐使用$((运算符形式))"
echo "  1. $((8 + 8 * 8))"
# shellcheck disable=SC2007
echo "  2. $[8 + 8 * 8]"
# expr
echo "  3. expr 8 + 8 * 8"
echo "注意: 和声明变量不同,expr运算符间要有空格, 乘号还要转义 /*, 而且还不能运算两个以上的数字"

echo "========================= if条件判断 ========================="
echo "基本语法 [ condition ] (注意 condition 前后要有空格)"
echo "注意: condition可以是字符串: 条件非空即为true, [ wyf ] 返回true, [] 返回false"
echo "      也可以是条件表达式"
echo "注意: 在命令行中可以查询$?, 为0,代表是true, 但是在sh脚本中不管是执行了true和false分支,都是0"

echo "========================= (1) 字符串比较 ========================="
echo "= 字符串比较"
# shellcheck disable=SC2034
str="hello"
if [ "$str" ]; then
  echo "true: 字符串{$str}不为空"
else
  echo "false: 字符串{$str}为空"
fi

echo "========================= (2) 两个整数之间的比较 ==================="
echo "-lt 小于(less than)              -le 小于等于(less equal)"
echo "-eq 等于(equal)                  -ne 不等于(not equal) "
echo "-gt 大于(greater than)           -ge 大于等于(greater equal)"
# shellcheck disable=SC2050
if [ 23 -ge 22 ]; then
  echo "true: 23 >= 22"
else
  echo "false: 23 < 22"
fi

echo "========================= (3) 按照文件权限进行判断 ==================="
echo "-r 有读的权限(read)"
echo "-w 有写的权限(write)"
echo "-x 有执行的权限(execute)"

echo "========================= (4) 按照文件类型进行判断 ==================="
echo "-e 文件存在(exist)"
echo "-f 文件存在并且是一个常规的文件(file)"
echo "-d 文件存在并且是一个目录(directory)"

if [ -d hello.sh ]; then
  echo "true: hello.sh 是directory"
else
  echo "false: hello.sh 不是directory"
fi

echo "========================= 流程控制(重点) ==================="

echo "========================= (1) if判断 ==================="
echo "基本语法: if 后要有空格和fi闭环"
echo "if [ condition ]; then"
echo "   true分支 "
echo "fi"

echo "======  elif 和 else ======"
echo "
      if [ condition ]; then
          commands;
      elif [ condition ]; then
          commands;
      else
         commands;
      fi"

echo "========================== (2) case语句 ========================"

# shellcheck disable=SC2162
# read -p "please input a number to case statement:" num #打印信息提示用户输入,输入信息赋值给num变量
num=3
case "$num" in
1)
    echo "The num you input is 1"
    ;;
[2-5])
    echo "The num you input is 2-5"
    ;;
[6-9])
    echo "The num you input is 6-9"
    ;;
*)
    echo "please input number[1-9] int"
esac

echo "========================== (3) for循环 ========================"
sum=0
for ((i = 1; i <= 100; i++))
do
  sum=$((sum + i))
done
echo "1~100的累加和: $sum"

echo "遍历输入参数: "
for p in "$@"
do
  echo "爱妃: $p"
done

sum2=0
k=1
while [ $k -le 50 ]
do
  sum2=$((sum2 + k))
  k=$((k + 1))
done
echo "1~50的累加和: $sum2"

#echo "========================== (3) read读取控制台输入 ========================"
#read -r -p "请输入你喜欢的演员, -r可以正常读取反斜杠: " girlName
#echo "$girlName 是你的女朋友"
#read -r -t 3 -p "请在三秒内输入另一个女明星: " other
#
#if [ "$other" ]; then
#  echo "$other 也是你的女朋友"
#else
#  echo "我就知道你很专一"
#fi

echo "========================== 系统函数 ========================"
echo "========================== (1) basename ========================"
# 基本语法: basename NAME [SUFFIX]
# 删除前导目录, 打印名称
# 如果指定,还可以删除后缀
# $(cmd) 指定输出
fileNameWithSuffix=$(basename include/stdio.h)
echo "$fileNameWithSuffix"  # stdio.h
fileName=$(basename include/stdio.h .h)
echo "$fileName" # stdio

echo "========================== (2) dirname ========================"
# Usage: dirname [OPTION] NAME...
# 输出 Name的所在最后一个斜杠之前的内容(NAME所在目录部分,且删除最后一个斜杠)
# 如果Name不包含斜杆,则输入 '.' ,代表当前目录
dir1=$(dirname /usr/bin/)
dir2=$(dirname /AuI18N/2052/usr/bin/a.txt)
dir3=$(dirname stdio.h)
echo "dir1: $dir1"
echo "dir2: $dir2"
echo "dir3: $dir3"


echo "========================== 自定义函数 ========================"
echo "标准写法: "
function name() {

    echo "== name() =="
    return 0
    # [return value], value取值范围是0-255
    # 表示函数的返回值,可写可不写
}
name
# 函数返回值只能通过$?系统变量获得,可以显示加。如果不加,讲以最后一条命令运行结果做回返回值
echo "func result : $?"

function twoSum() {
  s=0
  s=$(($1+$2))
  echo "twoSum result : $s"
}

# 调用 Shell 函数时可以给它传递参数,也可以不传递
# 如果不传递参数,直接给出函数名字即可:name
# 如果传递参数,那么多个参数之间以空格分隔:name param1 param2 param3
twoSum 6 6

echo "========================== sed ========================"
echo "Usage: sed [选项] 'command' fileName"
echo " -n, --quiet, --silent 只打印匹配行"
echo "也可以用数字开头,代表对指定行操作"
echo " 常用命令: s替换 d删除 p打印 q退出 i行前 a行后"
echo "-e 和 ; 都可以实现多条cmd"
#sed "s/u/UC/g" abc.txt  # u ==> UC, g代表整行都替换
#echo "=="
#sed "s/u/UC/" abc.txt
# sed "s/a//g" abc.txt   # 把所有的a都删掉了
# sed "s/#.*//g" abc.txt   # -i 会对源文件进行修改
# sed "s/\s*#.*//g" abc.txt   # \s*代表0或多个空格
# sed "s/\s*#.*//g; /^$/d" abc.txt # /^$/d删除空行
# sed "/a/q" abc.txt # 遇到第一个a就退出
# sed -n "/a/p" abc.txt # 打印匹配到a的行
# sed "3q" abc.txt # 打印到第三行就退出
# sed "3p" abc.txt # 到第三行就打印
#sed "/^wo/a cao" abc.txt # a 在匹配行后加一行
#sed "/^wo/i ai~" abc.txt  # i 在匹配行前加一行
#cmd1="2a mei nv22"
#sed "$cmd1" abc.txt
#sed "3s/a/TT/g" abc.txt # 只给第三行的a换成了TT
#sed "/lai/d" abc.txt
#sed "4d;s/wo/ni/g" abc.txt  # ; 号实现多条命令,删除第四行,且替换字符
#sed -e "4d" -e "s/wo/ni/g" abc.txt  # ; 号实现多条命令,删除第四行,且替换字符

echo "============================== awk ============================="
echo "常用函数:
tolower():字符转为小写。
length():返回字符串长度。
substr():返回子字符串。
rand():随机数。
"
echo "一个强大的文本分析工具,把文件逐行读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理"
echo "awk [选项参数] 'pattern1{action1} pattern2{action2}...'" fileName
echo "pattern : 表示awk在数据中查找的内容"
echo "action  : 在找到所匹配内容时所执行的一系列命令"
echo "常用选项参数 -F 指定分隔符"
echo "常用选项参数 -v 定义变量, awk的变量是与世隔绝的,里面取不到外面的,外面的也取不到里面的"
awk -F ":" '/^root/ {print $7}' demo.txt
awk -F ":" '/^root/ {print $1 ", " $7}' demo.txt
awk -F ":" '/^root/ {printf("第一列内容是%s, 第7列内容是: %s  ! \n", $1, $7)}' demo.txt
# BEGIN 和 END
awk -F ":" 'BEGIN{print "=== lu ben wei niu bi~ ==="}
            /^root/ {printf("第一列内容是%s, 第7列内容是: %s  ! \n", $1, $7)}
            END{print "=== bi xv di ! ==="}' demo.txt

awk -F ":" 'BEGIN{print "=== lu ben wei niu bi~ ==="}
            {printf("第一列内容是%s, 第7列内容是: %s  ! \n", $1, $7)}
            END{print "=== bi xv di ! ==="}' demo.txt
awk -F ":" -v i=1 '{print $3 + i}' demo.txt # 定义变量,给第三列加1
# awk 内置变量
awk -F ":" '{printf("文件名: %s, 行号: %s, 该行一共 %s 列, 第一列: %s \n", FILENAME, NR, NF, $1)}' demo.txt
# 打印空行的行号
awk '/^$/ {printf("空行行号: %s \n", NR)}' demo.txt

echo "================== wc ================="
echo "Usage: wc [OPTION]... [FILE]..."
echo "wc 会把文件名称打印出来,可以用awk去除"
total_lines=$(wc -l demo.txt | awk -F " " '{print $1}')
total_bytes=$(wc -c demo.txt | awk -F " " '{print $1}')
echo "demo.txt ==>> 总行数: $total_lines, 总字节数: $total_bytes"

echo "================ sort =================="
echo "Usage: sort [OPTION]... [FILE]..."
echo "
-n, 按照数值排序
-r, 反序
-b, 忽略前导空格
-t, 指定排序时所用的栏位分隔字符
-k, 指定排序的列
"
echo "按照日排序(第三列)"
sort -t "-" -k 3 -n sort.txt
sort -t "-" -k 3 -n -r sort.txt

4. 实操

1. 基础

# 利用for循环建立user1~~user5总共五个账号,并且密码均为redhat
# 提示man passwd命令中以标准输入方式给予账号密码。
vim user.sh
#!/bin/bash
for i in {1..5}
do
        useradd user$i
        echo redhat | passwd --stdin user$i
done
sh user.sh

# 访问网页
#!/bin/bash
url=http://127.0.0.1
code=$(curl -s -I -m 2 -o /dev/null $url -w %{http_code})
if [ "$code" -eq 200 ]; then
        echo "page is ok"
else
        echo "404"
fi

# 输入输出
#!/bin/bash

echo "输入用户名: "  
#读取从键盘的输入  
read username
id $username &> /dev/null
if [ $? -eq 0 ] ; then
        echo "user exists"
else
        useradd ${username}
fi

# case
#!/bin/bash

case $1 in
        a|A)
                echo a;;
        b|B)
                echo b;;
        *)
                echo none;;
esac

# 测试ping
#!/bin/bash

for i in {1..20}
do
        ping -c 5192.168.70.$i &> /dev/null
        if [ $? -eq 0 ];then
                echo "192.168.70.$i is up"
        else
                echo "192.168.70.$i is down"
        fi
done


# 九九乘法表
#!/bin/bash

for((i=1;i<=9;i++))
do
        for((j=1;j<=i;j++))
        do
                echo -n "${j}x${i}=$[i*j] "
        done
        echo 
done


# 控制台给函数传参
#!/bin/bash
#test()
{
        echo "$1 and $2"
}
#test 1 2

2. 常见问题

#!/bin/bash
# 计算demo.txt第三列总和
third_sum=$(awk -F ":" -v sum=0 '{sum+=$3} END{print sum}' demo.txt)
echo "第三列的和是: $third_sum"
unset third_sum

# 判断一个文件是否存在
if [ -f sort.txt ]; then
    echo "sort.txt 文件存在"
else
    echo "sort.txt 文件不存在"
fi

# 在当前目录查找包含字符 shen 的文件名称
# uniq 去重
# uniq 在后面显示行重复次数
grep -r shen | awk -F ":" '{print $1}' | uniq -c

# 输出 0 ~ 500 之间7的倍数
#for ((i = 0; i <= 500; i++))
#do
#  if [ $((i % 7)) -eq 0 ]; then
#    echo "$i"
#  fi
#done
#unset "$i"
#exit 0

#for i in {0..500}
#do
#  if [ $((i % 7)) -eq 0 ]; then
#    echo "$i"
#  fi
#done
#unset "$i"
#exit 0

# 生成 0 ~ 500的数字, 步长为7
# seq 0 7 500

# 写一个 bash脚本以统计一个文本文件 nowcoder.txt中字母数小于8的单词。
#
#
#
#示例:
#假设 nowcoder.txt 内容如下:
#how they are implemented and applied in computer
#
#你的脚本应当输出:
#how
#they
#are
#and
#applied
#in
awk '{
  for (i=1; i <= NF; i++) {
      if (length($i) < 8){
          print $i
      }
  }
}' n.txt

# 打印出空行,或者只有空格和制表符的行
awk 'NF == 0 {print NR}' n.txt

# 统计每个单词出现的次数
echo "===!!@@====="
awk '{
    for (i=1; i <= NF; i++) {
        print $i
    }
}' now.txt | sort | uniq -c | awk '{printf("%s %s\n", $2, $1)}' | sort -k 2 -n > res.txt

echo "====="
awk '{
 for (i = 1; i <= NF; ++i)
     mp[$i]++;
}
END {
 for (k in mp)
     printf("%s %d\n", k, mp[k]);
}' now.txt | sort -k 1 -n


awk '{print $2}' nowcoder.txt |
sort -n |
uniq -c |
awk '$1 > 1 {print $0}'


echo "
假设每行列数相同,并且每个字段由空格分隔

示例:
假设 nowcoder.txt 内容如下:
job salary
c++ 13
java 14
php 12

你的脚本应当输出(以词频升序排列):
job c++ java php
salary 13 14 12
"
cols=$(sed "1q" nowcoder.txt | awk '{print NF}')
for ((i = 1; i <= cols; i++)); do
    awk -v k="$i" '{printf("%s ", $k)}' nowcoder.txt
    echo
done

echo "
写一个 bash脚本以统计一个文本文件 nowcoder.txt中每一行出现的1,2,3,4,5数字个数
并且要计算一下整个文档中一共出现了几个1,2,3,4,5数字数字总数。

示例:
假设 nowcoder.txt 内容如下:
a12b8
10ccc
2521abc
9asf
你的脚本应当输出:
line1 number: 2
line2 number: 1
line3 number: 4
line4 number: 0
sum is 7
"
awk -F "" '
BEGIN{sum = 0}
{
    count = 0;
    for (i = 0; i < NF; i++) {
        if ($i == 1 || $i == 2 || $i == 3 || $i == 4 || $i == 5) {
            count++;
        }
    }
    sum += count;
    printf("line%s number:%d\n", NR, count);
}
END{printf("sum is %d\n", sum)}
' nowcoder.txt


echo "
写一个bash脚本以实现一个需求,求输入的一个的数组的平均值

第1行为输入的数组长度N
第2~N行为数组的元素,如以下为:
数组长度为4,数组元素为1 2 9 8
示例:
4
1
2
9
8

那么平均值为:5.000(保留小数点后面3位)
你的脚本获取以上输入应当输出:
5.000
"
awk 'BEGIN{sum = 0; len = 0}
{
    if (NR == 1) {
        len = $1;
    } else {
        sum += $1;
    }
}
END{printf("%0.3f\n", sum / len)}'


# xargs
应用场景1: 批量更改当前目录下的文件名
ls ./ | xargs -I GG echo "mv GG prefix_GG"
ls ./ | xargs -I GG mv GG prefix_GG

也可以这样批量更改该文件下的文件名
for i in ./*; do
  name=$(basename "$i")
  echo "mv $name sup_$name"
done

3. 获取硬件信息

#!/bin/bash

#CPU型号
cpu_model=`cat /proc/cpuinfo | grep "model name" | awk -F ':' '{print $2}' | sort | uniq`
echo "$cpu_model"

#CPU架构
cpu_architecture=`uname -m`
echo "$cpu_architecture"

#物理CPU个数
cpu_phy_num=`cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l`
echo "$cpu_phy_num"

#CPU核数
cpu_core_num=`cat /proc/cpuinfo | grep "cpu cores" | uniq | awk -F ': ' '{print $2}'`
echo "$cpu_core_num"

#逻辑CPU个数
cpu_proc_num=`cat /proc/cpuinfo | grep "processor" | uniq | wc -l`
echo "$cpu_proc_num"

##CPU主频
cpu_main_freq=`cat /proc/cpuinfo | grep "model name" | awk -F '@' 'NR==1 {print $2}'`
echo "$cpu_main_freq"

##L1d缓存
cpu_l1d_cache=`lscpu | grep -i 'L1d 缓存\|L1d cache' | awk -F ':|:' '{print $2}'`
echo "$cpu_l1d_cache"

##L1i缓存
cpu_l1i_cache=`lscpu | grep -i 'L1i 缓存\|L1i cache' | awk -F ':|:' '{print $2}'`
echo "$cpu_l1i_cache"

##L2缓存
cpu_l2_cache=`lscpu | grep -i 'L2 缓存\|L2 cache' | awk -F ':|:' '{print $2}'`
echo "$cpu_l2_cache"

##L3缓存
cpu_l3_cache=`lscpu | grep -i 'L3 缓存\|L3 cache' | awk -F ':|:' '{print $2}'`
echo "$cpu_l3_cache"

#操作系统名称
system_name=`head -n 1 /etc/issue | awk '{print $1,$2}'`
echo "$system_name"

#操作系统位数
systembit=`getconf LONG_BIT`
echo "$systembit"

#操作系统内核版本
system_kernel=`uname -r`
echo "$system_kernel"


#物理内存容量
meminfo=`sudo dmidecode | grep "^[[:space:]]*Size.*MB$" | uniq -c | sed 's/ \t*Size: /\*/g' | sed 's/^ *//g'`
echo "$meminfo"

#单位转换函数
function convert_unit()
{
	result=$1
	if [ $result -ge  1048576 ]
	then
		value=1048576 #1024*1024	
		result_gb=$(awk 'BEGIN{printf"%.2f\n",'$result' / '$value'}') #将KB转换成GB,并保留2位小数
		echo $result_gb"GB"
	elif [ $result -ge  1024 ]
	then
		value=1024 	
		result_mb=$(awk 'BEGIN{printf"%.2f\n",'$result' / '$value'}') #将KB转换成MB,并保留2位小数
		echo $result_mb"MB"
	else
		echo $result"KB"
	fi
}

#单位:KB
MemTotal=$(cat /proc/meminfo | awk '/^MemTotal/{print $2}') #内存总量
MemFree=$(cat /proc/meminfo | awk '/^MemFree/{print $2}')   #空闲内存
MemUsed=$(expr $MemTotal - $MemFree)  #已用内存

##计算内存占用率
Mem_Rate=$(awk 'BEGIN{printf"%.2f\n",'$MemUsed' / '$MemTotal' *100}') #保留小数点后2位

MemShared=$(cat /proc/meminfo | awk '/^Shmem/{print $2}') #共享内存
Buffers=$(cat /proc/meminfo | awk '/^Buffers/{print $2}') #文件缓冲区
Cached=$(cat /proc/meminfo | awk '/^Cached/{print $2}') #用于高速缓冲存储器

SwapTotal=$(cat /proc/meminfo | awk '/^SwapTotal/{print $2}') #交换区总量
SwapFree=$(cat /proc/meminfo | awk '/^SwapFree/{print $2}') #空闲交换区
Mapped=$(cat /proc/meminfo | awk '/^Mapped/{print $2}') #已映射

##虚拟内存
VmallocUsed=$(cat /proc/meminfo | awk '/^VmallocUsed/{print $2}') #已使用的虚拟内存

echo "$(convert_unit $MemTotal)"
echo "$(convert_unit $MemFree)"
echo "$(convert_unit $MemUsed)"
echo "$Mem_Rate%"
echo "$(convert_unit $MemShared)"
echo "$(convert_unit $Buffers)"
echo "$(convert_unit $Cached)"
echo "$(convert_unit $SwapTotal)"
echo "$(convert_unit $SwapFree)"
echo "$(convert_unit $Mapped)"
echo "$(convert_unit $VmallocUsed)"


#磁盘型号
disk_model=`fdisk -l | grep "Disk model" | awk -F : '{print $2}' | sed 's/^ //'`
echo "$disk_model"

usesum=0
totalsum=0
disknum=`df -hlT |wc -l `
for((n=2;n<=$disknum;n++))
do
	use=$(df -k |awk NR==$n'{print int($3)}')
	pertotal=$(df -k |awk NR==$n'{print int($2)}')
	usesum=$[$usesum+$use]		#计算已使用的总量
	totalsum=$[$totalsum+$pertotal]	#计算总量
done
freesum=$[$totalsum-$usesum]
diskutil=$(awk 'BEGIN{printf"%.2f\n",'$usesum' / '$totalsum'*100}')
freeutil=$(awk 'BEGIN{printf"%.2f\n",100 - '$diskutil'}')

#磁盘总量
if [ $totalsum -ge 0 -a $totalsum -lt 1024 ];then
echo "$totalsum K"

elif [ $totalsum -gt 1024 -a  $totalsum -lt 1048576 ];then
	totalsum=$(awk 'BEGIN{printf"%.2f\n",'$totalsum' / 1024}')
echo "$totalsum M"

elif [ $totalsum -gt 1048576 ];then
	totalsum=$(awk 'BEGIN{printf"%.2f\n",'$totalsum' / 1048576}')
echo "$totalsum G"

fi

#磁盘已使用总量
if [ $usesum -ge 0 -a $usesum -lt 1024 ];then
echo "$usesum K"

elif [ $usesum -gt 1024 -a  $usesum -lt 1048576 ];then
	usesum=$(awk 'BEGIN{printf"%.2f\n",'$usesum' / 1024}')
echo "$usesum M"

elif [ $usesum -gt 1048576 ];then
	usesum=$(awk 'BEGIN{printf"%.2f\n",'$usesum' / 1048576}')
echo "$usesum G"

fi

#磁盘未使用总量
if [ $freesum -ge 0 -a $freesum -lt 1024 ];then
echo "$freesum K"

elif [ $freesum -gt 1024 -a  $freesum -lt 1048576 ];then
	freesum=$(awk 'BEGIN{printf"%.2f\n",'$freesum' / 1024}')
echo "$freesum M"

elif [ $freesum -gt 1048576 ];then
	freesum=$(awk 'BEGIN{printf"%.2f\n",'$freesum' / 1048576}')
echo "$freesum G"
fi

#磁盘占用率
echo "$diskutil%"

#磁盘空闲率
echo "$freeutil%"


#显卡型号
graphicscardmodel=`lspci | grep -i 'VGA' | sed '2d' | cut -f3 -d ":" | sed 's/([^>]*)//g'`
echo "$graphicscardmodel"

#显卡生产商
graphicscardmanufacturer=`lspci | grep -i 'VGA'| sed '2d'| awk '{ print $5,$6 }'`
echo "$graphicscardmanufacturer"



#主板厂商
boardmanufacturer=`sudo dmidecode | grep -A 10 "Base Board Information" |grep "Manufacturer" | awk -F ':' '{print $2}'`
echo "$boardmanufacturer"

#主板名称
boardname=`sudo dmidecode | grep -A 10 "Base Board Information" |grep "Product Name" | awk -F ':' '{print $2}'`
echo "$boardname"

#BIOS厂商
biosvendor=`sudo dmidecode | grep -A 28 "BIOS Information" | grep 'Vendor' | awk -F ':' '{print $2}'`
echo "$biosvendor"

#BIOS版本
biosversion=`sudo dmidecode | grep -A 28 "BIOS Information" | grep 'Version' | awk -F ':' '{print $2}'`
echo "$biosversion"

#BIOS发行日期
biosrelease=`sudo dmidecode | grep -A 28 "BIOS Information" | grep 'Release' | awk -F ':' '{print $2}'`
echo "$biosrelease"

#网卡信息
netcardinfo=`lspci | grep -i eth | head -n +1 | awk -F : '{print $3}' | sed 's/^ //'`
echo "$netcardinfo"

4. 获取硬件使用率

#!/bin/bash
# 获取要监控的本地服务器IP地址
IP=`ifconfig | grep inet | grep -vE 'inet6|127.0.0.1' | awk '{print $2}'`
echo "IP地址:"$IP
 
# 获取cpu总核数
cpu_num=`grep -c "model name" /proc/cpuinfo`
echo "cpu总核数:"$cpu_num
 
# 1、获取CPU利用率
################################################
#us 用户空间占用CPU百分比
#sy 内核空间占用CPU百分比
#ni 用户进程空间内改变过优先级的进程占用CPU百分比
#id 空闲CPU百分比
#wa 等待输入输出的CPU时间百分比
#hi 硬件中断
#si 软件中断
#################################################
# 获取用户空间占用CPU百分比
cpu_user=`top -b -n 1 | grep Cpu | awk '{print $2}' | cut -f 1 -d "%"`
echo "用户空间占用CPU百分比:"$cpu_user
 
# 获取内核空间占用CPU百分比
cpu_system=`top -b -n 1 | grep Cpu | awk '{print $4}' | cut -f 1 -d "%"`
echo "内核空间占用CPU百分比:"$cpu_system
 
# 获取空闲CPU百分比
cpu_idle=`top -b -n 1 | grep Cpu | awk '{print $8}' | cut -f 1 -d "%"`
echo "空闲CPU百分比:"$cpu_idle
 
# 获取等待输入输出占CPU百分比
cpu_iowait=`top -b -n 1 | grep Cpu | awk '{print $10}' | cut -f 1 -d "%"`
echo "等待输入输出占CPU百分比:"$cpu_iowait
 
#2、获取CPU上下文切换和中断次数
# 获取CPU中断次数
cpu_interrupt=`vmstat -n 1 1 | sed -n 3p | awk '{print $11}'`
echo "CPU中断次数:"$cpu_interrupt
 
# 获取CPU上下文切换次数
cpu_context_switch=`vmstat -n 1 1 | sed -n 3p | awk '{print $12}'`
echo "CPU上下文切换次数:"$cpu_context_switch
 
#3、获取CPU负载信息
# 获取CPU15分钟前到现在的负载平均值
cpu_load_15min=`uptime | awk '{print $11}' | cut -f 1 -d ','`
echo "CPU 15分钟前到现在的负载平均值:"$cpu_load_15min
 
# 获取CPU5分钟前到现在的负载平均值
cpu_load_5min=`uptime | awk '{print $10}' | cut -f 1 -d ','`
echo "CPU 5分钟前到现在的负载平均值:"$cpu_load_5min
 
# 获取CPU1分钟前到现在的负载平均值
cpu_load_1min=`uptime | awk '{print $9}' | cut -f 1 -d ','`
echo "CPU 1分钟前到现在的负载平均值:"$cpu_load_1min
 
# 获取任务队列(就绪状态等待的进程数)
cpu_task_length=`vmstat -n 1 1 | sed -n 3p | awk '{print $1}'`
echo "CPU任务队列长度:"$cpu_task_length
 
#4、获取内存信息
# 获取物理内存总量
mem_total=`free | grep Mem | awk '{print $2}'`
echo "物理内存总量:"$mem_total
 
# 获取操作系统已使用内存总量
mem_sys_used=`free | grep Mem | awk '{print $3}'`
echo "已使用内存总量(操作系统):"$mem_sys_used
 
# 获取操作系统未使用内存总量
mem_sys_free=`free | grep Mem | awk '{print $4}'`
echo "剩余内存总量(操作系统):"$mem_sys_free
 
# 获取应用程序已使用的内存总量
mem_user_used=`free | sed -n 3p | awk '{print $3}'`
echo "已使用内存总量(应用程序):"$mem_user_used
 
# 获取应用程序未使用内存总量
mem_user_free=`free | sed -n 3p | awk '{print $4}'`
echo "剩余内存总量(应用程序):"$mem_user_free
 
 
# 获取交换分区总大小
mem_swap_total=`free | grep Swap | awk '{print $2}'`
echo "交换分区总大小:"$mem_swap_total
 
# 获取已使用交换分区大小
mem_swap_used=`free | grep Swap | awk '{print $3}'`
echo "已使用交换分区大小:"$mem_swap_used
 
# 获取剩余交换分区大小
mem_swap_free=`free | grep Swap | awk '{print $4}'`
echo "剩余交换分区大小:"$mem_swap_free
 

#5、获取磁盘I/O统计信息
echo "指定设备(/dev/sda)的统计信息"
# 每秒向设备发起的读请求次数
disk_sda_rs=`iostat -kx | grep sda| awk '{print $4}'`
echo "每秒向设备发起的读请求次数:"$disk_sda_rs
 
# 每秒向设备发起的写请求次数
disk_sda_ws=`iostat -kx | grep sda| awk '{print $5}'`
echo "每秒向设备发起的写请求次数:"$disk_sda_ws
 
# 向设备发起的I/O请求队列长度平均值
disk_sda_avgqu_sz=`iostat -kx | grep sda| awk '{print $9}'`
echo "向设备发起的I/O请求队列长度平均值"$disk_sda_avgqu_sz
 
# 每次向设备发起的I/O请求平均时间
disk_sda_await=`iostat -kx | grep sda| awk '{print $10}'`
echo "每次向设备发起的I/O请求平均时间:"$disk_sda_await
 
# 向设备发起的I/O服务时间均值
disk_sda_svctm=`iostat -kx | grep sda| awk '{print $11}'`
echo "向设备发起的I/O服务时间均值:"$disk_sda_svctm
 
# 向设备发起I/O请求的CPU时间百分占比
disk_sda_util=`iostat -kx | grep sda| awk '{print $12}'`
echo "向设备发起I/O请求的CPU时间百分占比:"$disk_sda_util

5. 密码比对

#!/bin/bash
COUNT=0
PASSWD=12345

while [ $COUNT -lt 3 ]
do
        read -p "input passwd:" password
        if [ "$password" = "$PASSWD" ];then
                echo "right"
                exit
        else
                echo "wrong"
                let COUNT++
        fi
done
echo "too many wrong!"

6. 磁盘监控

df -hl 查看磁盘剩余空间
 
df -h 查看每个根路径的分区大小
 
du -sh [目录名] 返回该目录的大小
 
du -sm [文件夹] 返回该文件夹总M数
 
du -h [目录名] 查看指定文件夹下的所有文件大小(包含子文件夹)

查看硬盘的分区 #sudo fdisk -l

查看IDE硬盘信息 #sudo hdparm -i /dev/hda

查看STAT硬盘信息 #sudo hdparm -I /dev/sda 或 #sudo apt-get install blktool #sudo blktool /dev/sda id

查看硬盘剩余空间 #df -h #df -H

查看目录占用空间 #du -hs 目录名

使用命令查看指定目录空间情况,例如查看opt目录

du -h --max-depth=1 /opt


#!/bin/bash

echo "磁盘当前实时读写速率:"
# 每秒向设备发起的读请求次数
disk_sda_rs=`iostat -kx | grep sda| awk '{print $4}'`
echo "每秒向设备发起的读请求次数:"$disk_sda_rs

# 每秒向设备发起的写请求次数
disk_sda_ws=`iostat -kx | grep sda| awk '{print $5}'`
echo "每秒向设备发起的写请求次数:"$disk_sda_ws



max_filesys_use=`df -h | sort -nr -k5 | head -n1`
echo "最大文件系统使用率:"
echo $max_filesys_use

echo "磁盘使用情况:"
df -h | grep "/dev/sda"
disk_use=`df -h | grep "/dev/sda" | awk '{print $5}' | cut -d '%' -f 1`

echo "磁盘使用率: $disk_use%"

echo "inode监控:"
df -i

Logo

更多推荐