shell指令碼程式設計筆記

oliver-l發表於2020-08-26

最近在學習shell程式設計,通過學習慕課課程跟著360架構師 學習Shell指令碼程式設計,於是將課程中有的例子都敲了一遍,在此記錄一下。後續還會繼續寫一些指令碼例子玩玩。

例題1:
變數string=‘Bigdata process framework is Hadoop,Hadoop is an open source programm’,執行指令碼後,列印輸出string變數字串,並給使用者以下選項:
(1)列印變數長度
(2)刪除字串中所有的Hadoop
(3)替換第一個Hadoop為Mapreduce
(4)替換全部Hadoop為Mapreduce
使用者輸入陣列1|2|3|4,可以執行對應的功能:輸入q|Q則退出互動模式

#!/bin/bash

string='Bigdata process framework is Hadoop,Hadoop is an open source programm'

function print_tips()
{
    echo '====================================='
    echo "變數string=${string}"
    echo '輸入1,列印變數長度'
    echo '輸入2,刪除字串中所有的Hadoop'
    echo '輸入3,替換第一個Hadoop為Mapreduce'
    echo '輸入4,替換全部Hadoop為Mapreduce'
    echo '輸入q|Q退出指令碼'
    echo '====================================='
}

function print_strlen()
{
    echo "字串長度為:${#string}"
}

function print_delete_hadoop()
{
    echo "刪除字串中所有的Hadoop,字串為:${string//Hadoop}"
}

function print_replace_hadoop()
{
    echo "替換第一個Hadoop為Mapreduce,字串為:${string/Hadoop/Mapreduce}"
}

function print_replace_all_hadoop()
{
    echo "替換全部Hadoop為Mapreduce,字串為:${string//Hadoop/Mapreduce}"
}

#print_tips
#print_strlen
#print_delete_hadoop
#print_replace_hadoop
#print_replace_all_hadoop

while True
do
  print_tips
  # shellcheck disable=SC2162
  read -p '請輸入指令:' input
  case $input in
  1)
    print_strlen
    ;;
  2)
    print_delete_hadoop
    ;;
  3)
    print_replace_hadoop
    ;;
  4)
    print_replace_all_hadoop
    ;;
  q|Q)
      echo '退出指令碼'
    exit
    ;;
  *)
    echo '無效指令'
    ;;
  esac

done

例題2
編寫一個script, 建立目錄/tmp/scripts, 切換工作目錄到此目錄中,複製你home下的words.txt到當前目錄,並重新命名為test,將test裡的檔案及其下的目錄的其他使用者許可權改為沒有任何許可權。

#!/bin/bash

echo '============================='
echo '建立目錄'
mkdir /tmp/scripts

echo '=============================='
echo '切換到新建目錄'
cd /tmp/scripts
directory=`pwd`
echo "當前工作目錄為:${directory}"

user=`whoami`
userDirectory="/Users/${user}"
echo ${userDirectory}
echo '==============================='
echo '複製txt文化到/tmp/scripts目錄'
cp "${userDirectory}/words.txt" /tmp/scripts/test.txt

echo '================================'
echo '修改檔案許可權'
chmod 700 /tmp/scripts/test.txt

例題3
根據系統時間獲取今年還剩下多少星期,已經過了多少星期

#!/bin/bash

date=`date "+%j"`
echo "今年已經過了$(($date/7))星期"
echo "今年還剩下$(((365-$date)/7))星期"

例題4
判斷nginx程式是否存在,若不存在則自動拉起該程式

#!/bin/bash

check=`ps -ef | grep nginx | grep -v color | wc -l`

if [ $check -eq 1 ];then
        `sudo nginx`
        echo 'nginx未開啟,現在開啟nginx'
else
        echo 'nginx已開啟'
fi

例題5
提示使用者輸入一個正整數num,然後計算1+2+3+…+num的值,必須對num是否為正整數進行判斷,不符合則讓使用者重新輸入

#!/bin/bash

while True
do
    read -p "請輸入一個正整數:" num
    expr $num + 1 &>/dev/null
    if [ $? -eq 0 ];then
        if [ $num -gt 0 ];then
          sum=0
            for((i=1;i<=num;i++))
            do
                sum=`expr $sum + $i`
            done
            echo "1+2+3+...+${num}=${sum}"
            exit
        else
            echo "輸入的字元不是正整數,請重新輸入"
        fi
    else
        echo "輸入的字元不是正整數,請重新輸入"
    fi
done

例題6

find命令用法例子

1.搜尋/etc目錄下的檔案(非目錄),檔名以conf結尾,且大於10k,然後將其刪除

find /etc -type f -name '*.conf' -size +10k -exec rm -f {}

2.將/var/log目錄下以log結尾的檔案,且更改時間在七天以上的刪除

find /var/log -name '*.log' -mtime +7 -exec rm -rf {}

3.搜尋條件和例子1一樣,只是不刪除,而是將其複製到/root/conf目錄下

find /etc -size +10k -type f -name '*.conf' -exec cp {} /root/conf

例題7.

grep命令用法例子

1.顯示/proc/meminfo檔案中以大小s開頭的行

cat /proc/meminfo |grep -i ^"s"

2.顯示/etc/passwd檔案中不以/bin/bash結尾的行

cat /etc/passwd|grep -v "/bin/bash"$

3.找出/etc/passwd中的兩位或三位數

cat /etc/passwd | grep -o "\<[1-9][0-9]\{1,2\}\>" | sort -nr | uniq

例題8.

sed命令用法例子

1.顯示/cat/passwd檔案的10-30行

sed -n '10,30p' /ect/passwd

2.顯示/cat/passwd檔案中包含root的行到包含shutdown的行

sed -n '/root/,/shutdown/p' /etc/passwd

3.在passwd檔案開頭插入hello

sed -i '1s/^/hello \n/g' passwd

4.將passwd檔案的nologin替換為nologin111

sed -i 's/nologin/nologin111/g' passwd

5.刪除passwd檔案中包含redis的行

sed -i '/redis/d' passwd

例題9.

處理一個類似MySQL配置檔案my.cnf,示例如下
編寫指令碼實現以下功能:輸出檔案有幾個段,並且針對每個段可以統計配置引數總個數

如下檔案配置my.cnf

[client]
#password    = your_password
port        = 3306
socket        = /tmp/mysql.sock

[mysqld]
port        = 3306
socket        = /tmp/mysql.sock
datadir = /www/server/data
default_storage_engine = InnoDB
performance_schema_max_table_instances = 400
table_definition_cache = 400
skip-external-locking
key_buffer_size = 64M
max_allowed_packet = 100G
table_open_cache = 256
sort_buffer_size = 1M
net_buffer_length = 4K
read_buffer_size = 1M
read_rnd_buffer_size = 256K
myisam_sort_buffer_size = 16M
thread_cache_size = 32
query_cache_size = 32M
tmp_table_size = 64M
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

explicit_defaults_for_timestamp = true
#skip-name-resolve
max_connections = 500
max_connect_errors = 100
open_files_limit = 65535

log-bin=mysql-bin
binlog_format=mixed
server-id = 1
expire_logs_days = 10
slow_query_log=1
slow-query-log-file=/www/server/data/mysql-slow.log
long_query_time=3
#log_queries_not_using_indexes=on


innodb_data_home_dir = /www/server/data
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = /www/server/data
innodb_buffer_pool_size = 256M
innodb_log_file_size = 128M
innodb_log_buffer_size = 32M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50
innodb_max_dirty_pages_pct = 90
innodb_read_io_threads = 2
innodb_write_io_threads = 2

[mysqldump]
quick
max_allowed_packet = 500M

[mysql]
no-auto-rehash

[myisamchk]
key_buffer_size = 64M
sort_buffer_size = 1M
read_buffer = 2M
write_buffer = 2M

[mysqlhotcopy]
interactive-timeout

預期輸出結果:
1.client 2
2.mysqld 41
3.mysqldump 2
4.mysql 1
5.myisamchk 4
6.mysqlhotcopy 1

#!/bin/bash

file='my.cnf'

function get_all_paragraph()
{
    echo "`sed -n '/\[*\]/p' $file | sed -e 's/\[//g' -e 's/\]//g'`"
}

function get_paragraph_config()
{
    echo "`sed -n '/\['$1'\]/,/\[*\]/p' $file | grep -v '\[*\]' | grep -v ^'#' | grep -v ^$ | wc -l`"
}

paragraphs=`get_all_paragraph`

index=0
for item in $paragraphs
do
  index=`expr $index + 1`
  count=`get_paragraph_config $item`
  echo "$index . $item $count"
done

例題10

1.刪除配置檔案中的所有註釋行和空行

sed -i '/^\s*$/d' *.conf && sed -i '/^[[:space:]]*#/d' *.conf

2.在配置檔案中所有不以#開頭的行前面新增*符號,注意:以#開頭的行不新增

sed -i '/^[^#]/s/^/*&/g' passwd
sed -i '/^[^#]/i *' passwd

例題11

1.以字串的格式列印/etc/passwd中的第7個欄位,以”:”作為分隔符

awk 'BEGIN{FS=":"}{printf "%s\n",$7}' /etc/passwd | grep -v ^$

2.以10進位制格式列印/etc/passwd中的第3個欄位,以”:”作為分隔符

awk 'BEGIN{FS=":"}{printf "%d\n",$3}' /etc/passwd | grep -v ^$

3.匹配/etc/passwd檔案中含有root字串的所有行

awk '/root/{print $0}' /etc/passwd

4.匹配/etc/passwd檔案行中以root開頭的所有行

awk '/^root/{print $0}' /etc/passwd

5.使用awk計算/etc/passwd中以#開頭的行數量

awk 'BEGIN{i=0}/^#/{i++}END{print i}' /etc/passwd

6.計算學生課程分數平均值,學生課程檔案如下

Allen 80 90 96 98
Mike 75 84 66 78
Jerry 91 58 45 87
Bill 84 58 68 55
Li 69 59 78 63 81

awk '{printf "%s:%0.2f\n",$1,($2+$3+$4+$5)/4}' words.txt

7.計算1+2+3+4+…+100的和,請使用while,do while,for三種迴圈方式實現

$>>vim for.awk

BEGIN{
        sum=0
        for(i=0;i<=100;i++)
        {
                sum+=i
        }
        print sum
}

$>>awk -f for.awk
$>>vim while.awk

BEGIN{
        sum=0;
        i=1;
        while(i<=100)
        {
                sum+=i
                i++
        }
        print sum
}

$>>awk -f while.awk
$>>vim dowhile.awk

BEGIN{
        sum=0
        i=1
        do{
                sum+=i
                i++
        }while(i<=100)
        print sum
}

$>>awk -f dowhile.awk

例題12

實現一個指令碼,可檢視配置下程式執行情況,輸出如下:

PROCESS_NAME GROUP STATUS PID CPU MEMORY START_TIME
nginx web RUNNING 59 0.0 0.0 8/26 09:10:05 2020

配置資訊如下:

[service]
Web
DB
Code

[Web]
nginx
apache

[DB]
mysql

[Code]
php
python

實現程式碼程式碼如下:

#! /bin/bash

conf_name='status.conf'

#得到group列表
function get_conf_group_list() {
    group_list=`sed -n '/\[service\]/,/\[*\]/p' $conf_name | grep -v '\[*\]' | grep -v '^$'`
    echo $group_list
}

#得到一個group下的資訊
function get_conf_item_list() {
    item_list=`sed -n '/\['$1'\]/,/\[*\]/p' $conf_name | grep -v '\[*\]' | grep -v '^$'`
    echo $item_list
}

#獲取所有項資料
function get_all_item() {
  index=1
  for item in `get_conf_group_list`
  do
    group_item=`get_conf_item_list $item`
    for item in $group_item
    do
      echo $item
    done
  done
}
#獲取服務pid
function get_service_pid() {
    service_ps=`ps -ef | grep $1 | grep -v $$ | grep -v grep | awk '{print $2}'`
    echo "$service_ps"
}

#檢查服務是否開啟
function check_service_is_alive() {
    check=`ps -ef | grep $1 | grep -v $$ | grep -v grep | wc -l`
    if [ $check -eq 0 ]; then
      return 1
#        echo "$1:STOPPED"
    else
      return 0
#        echo "$1:RUNNING"
    fi
}

#獲取程式cpu執行情況
function get_pid_cpu(){
  pid=`ps aux | grep $1 | grep -v $$ | grep -v grep | grep $2 | awk '{print $3;exit}'`
  echo $pid
}

#獲取程式記憶體執行情況
function get_pid_memory(){
  pid=`ps aux | grep $1 | grep -v $$ | grep -v grep | grep $2 | awk '{print $4;exit}'`
  echo $pid
}

function get_pid_lstart() {
    pid=`ps -p $1 -o lstart | grep -v STARTED | sed -e 's/三//g' -e 's/ /-/g'`
    echo $pid
}

awk 'BEGIN{printf "%-15s%-10s%-10s%-10s%-10s%-10s%-10s\n","PROCESS_NAME","GROUP","STATUS","PID","CPU","MEMORY","START_TIME"}'

for item in `get_conf_group_list`
do
  for sonItem in `get_conf_item_list $item`
  do
    check=`check_service_is_alive $sonItem`
    #停止允許
    if [ $? -eq 1 ]; then
      awk -v var1=$sonItem -v var2=$item 'BEGIN{printf "%-15s%-10s%-10s%-10s%-10s%-10s%-10s\n",var1,var2,"STOPPED","NULL","NULL","NULL","NULL"}'
    else
      for pid in `get_service_pid $sonItem`
      do
        cpu=`get_pid_cpu $sonItem $pid`
        memory=`get_pid_memory $sonItem $pid`
        lstart=`get_pid_lstart $pid`
        awk -v var1=$sonItem -v var2=$item -v var3=$pid -v var4=$cpu -v var5=$memory -v var6=$lstart 'BEGIN{printf "%-15s%-10s%-10s%-10s%-10s%-10s%-10s\n",var1,var2,"RUNNING",var3,var4,var5,var6}'
      done
    fi
  done
done
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章