shell基础回顾

0.vim命令

vim

复制代码
gg					移动到文档第一行
G   				移动到文档最后一行
:set nu 		显示行号
:set noun 	取消行号
nG					移动到指定n行,例如20G
$						移动到行尾
0						移动到行头
clrt+f 			屏幕向下移动一页
clrt+b 		  屏幕向上移动一页
:%s+word1+word2+g 搜索文本,将word1字符串,替换成word2字符串
x 					向后删除一个字符
X 					向前删除一个字符

shift+d 		删除当前行,光标后的字符
dd 					删除游标所在整行
ndd					删除光比所在向下n列,例如:3dd
yy 					复制游标所在行
p,P 				小p将已复制的数据在光标下一行粘贴,大P则为粘贴在游标上一行
u 					复原前一个动作,回退一步

i 					从当前光标插入
o, O  			小写的o当前光标下一行插入  大写的O当前光标上一行插入
r, R				小写的r替换字符,大写的R

:q!				强制退出不保存
:wq					保存

ZZ 					大写的ZZ,保持后快速退出(需要在esc退出编辑模式下操作)

ctrl+v			光标移动到215.18前,通过上下左右移动选择一块区域,选号后按y 复制,p 粘贴想要的内容


1          2      3      4                              5                     6
tcp        0      0 :::10302                    :::*                        LISTEN
tcp        0      0 ::ffff:172.16.10.205:10302  ::ffff:215.18.157.74:5660   ESTABLISHED
tcp        0      0 ::ffff:172.16.10.205:10302  ::ffff:110.182.143.19:27490 TIME_WAIT
tcp        0      0 ::ffff:172.16.10.205:10302  ::ffff:110.182.143.19:27489 TIME_WAIT
tcp        0      0 ::ffff:172.16.10.205:10302  ::ffff:219.66.163.171:52754 ESTABLISHED
tcp        0      0 ::ffff:172.16.10.205:10302  ::ffff:59.39.132.243:30368  TIME_WAIT

这样复制出来的结果就是:
215.18.157.74:5660
110.182.143.19:27490
110.182.143.19:27489
219.66.163.171:52754
59.39.132.243:30368

1.生成指定文件

shell 复制代码
#使用dd,if参数指定了输入文件(/dev/zero表示一个无限的全零字节流)
#of参数指定了输出文件的路径和名称(/root/1.log)
#bs参数指定了每次读取和写入的块大小(这里是10MB)
#count参数指定了要复制的块数(这里是1)
dd if=/dev/zero of=/root/1.log bs=10M count=1

2.shell压缩脚本

cat test.sh

shell 复制代码
#!/bin/bash

#要压缩的目录或者文件
source_dir="/mnt"

#压缩后输入的路径或者文件
output_file="/root/mnt.tar.gz"

#使用tar 命令压缩,通过 --exclude  过滤目录或者文件
tar zcvf "${output_file}" --exclude="/mnt/test"  --exclude="/mnt/1.log" "${source_dir}"

#打包
#tar zcvf 2020.tar.gz *2020*.log

#解压
#tar -zxvf ktgl20201207.tar.gz -C /data/webapp

#不想解压,查看压缩包内容
#tar ztvf ktgl20201207.tar.gz

3.自定义函数别名

shell 复制代码
#显示当前定义的所有别名
alias

#打开当前用户的.bashrc文件,自定义环境变量、别名和函数等设置
vim ~/.bashrc
#定义函数
testFunc(){
  ps -ef|grep nginx
}


#使变量生效
source ~/.bashrc


#定义别名
alias psnginx=testFunc

4.查看命令cat

shell 复制代码
#显示行号
cat -n myfile.txt

#显示特殊字符
cat -A myfile.txt

在cat命令后面添加选项-A(或-vET)可以改变输出格式,以显示一些特殊字符的可见表示。

具体来说,-A选项会将以下特殊字符添加到输出中:

  • 非打印字符(不包括换行符和制表符)会以^后接对应的控制字符形式显示。例如,ASCII 值为 1 的字符会显示为 ^A。
  • 行尾的 $ 符号会显示在每行的末尾。
  • 制表符会显示为 ^I。

这个选项通常用于显示一些看不见的特殊字符,以便进行文本分析或调试。

$ cat -A myfile.txt

This is a line of text.^M$

This is another line of text with a tab character. ^I$

#在上面的示例中,^M 表示回车符,^I 表示制表符,$ 表示行尾。

5.find命令

shell 复制代码
#查找ceph-csi-3.2.0目录下,所有的*log文件
find /ceph-csi-3.2.0/ -name "*log"

#查看/ceph-csi-3.2.0目录下所有*.sh文件每个的大小
#注:xargs组合多个命令的一个工具
find  /ceph-csi-3.2.0/ -type f -name "*.sh" | xargs du -sh

#复制/ceph-csi-3.2.0目录下所有*.sh文件到/root/test下
find  /ceph-csi-3.2.0/ -type f -name "*.sh" -exec cp -a {} /root/test \;



#/ceph-csi-3.2.0目录开始搜索文件,排除目录/ceph-csi-3.2.0/scripts/*,排除文件/ceph-csi-3.2.0/deploy.sh,查找*.sh文件
find /ceph-csi-3.2.0/ -type f -path "/ceph-csi-3.2.0/scripts/*" -o -path "/ceph-csi-3.2.0/deploy.sh" -o -type f -name "*.sh" -print



#比较下面两个打包的区别
#第一个是打包成一个文件
find /ceph-csi-3.2.0/ -type f -path "/ceph-csi-3.2.0/scripts/*" -o -path "/ceph-csi-3.2.0/deploy.sh" -o -type f -name "*.sh" -print | xargs tar zcvf allSh.tar.gz

#第二个是打包成多个文件
find /ceph-csi-3.2.0/ -type f -path "/ceph-csi-3.2.0/scripts/*" -o -path "/ceph-csi-3.2.0/deploy.sh" -o -type f -name "*.sh" -print -exec tar zcvf {}.tar.gz {} \;

6.ln 软链接和硬链接

shell 复制代码
#软链接
ln -svf /ceph-csi-3.2.0/allSh.tar.gz /root/
● -s:创建软链接(Symbolic Link),而不是创建硬链接。
● -v:显示详细的输出,即在创建链接时显示正在进行的操作。
● -f:强制执行操作,即如果目标文件已存在,则覆盖它。


#硬链接
ln /ceph-csi-3.2.0/allSh.tar.gz /root/

在Linux中,ln命令用于创建链接(link)文件。其中有两种类型的链接:软链接(Symbolic Link)和硬链接(Hard Link)。它们之间有以下区别:

  1. 路径类型:软链接是一个指向目标文件的路径名,而硬链接是一个指向目标文件的物理副本。
  2. 文件类型:软链接被视为一个独立的文件,它具有自己的 inode 和文件权限。硬链接是文件系统中原始文件的另一个名称,实际上它们共享相同的 inode 和文件权限。
  3. 跨文件系统:软链接可以跨越不同的文件系统,因为它们只是包含目标文件路径的文本文件。硬链接只能在同一文件系统内工作,因为它们依赖于 inode。
  4. 目标更新:如果目标文件被重命名、删除或移动,软链接将失效,而硬链接仍然有效,因为它们直接指向目标文件的物理副本。
  5. 目录链接:软链接可以链接到目录,而硬链接不能链接到目录。
  6. 多个链接:对于硬链接,可以有多个链接指向同一文件,而软链接只能有一个链接指向目标文件。

总之,软链接是指向目标文件路径的独立文件,可以跨文件系统并且保留原始文件的路径和权限信息。硬链接是原始文件的另一个名称,具有相同的inode和权限,不能跨越文件系统,并且在目标文件更改时仍然有效。

使用ln命令创建链接时,如果不指定任何选项,默认情况下会创建硬链接。要创建软链接,可以使用ln -s选项。

7.文件和目录对比

shell 复制代码
diff			文件内容对比命令(案例:diff 1.txt 2.txt)
du				查看文件或目录使用空间大小
basename	过滤出路径下面最后的文件名或目录
dirname		从文件名中删除最后一个组成部分
df				查看系统硬盘占用空间情况 (案例:df -TH)
df -i			查看磁盘inode使用空间

#查看目录下,低于100K的文件数量
find /mnt -type f -size -100k | wc -l

#删除低于100K,过多小文件
find /mnt -type f -size -100k |  xargs rm -f



[root@k8s-master01 jtpv]# basename /root/jtpv/pv.yaml
pv.yaml
[root@k8s-master01 jtpv]# dirname /root/jtpv/pv.yaml
/root/jtpv

8.目录或文件权限

shell 复制代码
[root@news-static ~]# ls -l 1.html
-rw-r--r--. 1 root root 0 12月 25 2019 1.html

[root@news-static ~]# ls -ld nginx-1.23.2
drwxr-xr-x. 9 1001 1001 4096 11月 30 2022 nginx-1.23.2



r	w	x
4	2	1
读 写 执or进入
0644/-rw-r--r--	#文件  
0755/drwxr-xr-x	#目录


0644+0022=0666 文件最大权限666
0755+0022=0777 目录最大权限777


umask
	0022 #第一位0: 表示这是一个八进制数


[root@news-static ~]# umask
0022
[root@news-static ~]# ls -l 1.html
-rw-r--r--. 1 root root 0 12月 25 2019 1.html


[root@k8s-master01 ~]# diff 1.txt 2.txt
12a13
> 123



chown			更改文件所有者以及所有组,常用-R 是目录内所有文件都授权
chattr +i	锁定文件
lsattr		显示文件或目录的扩展属性的命令
chattr +a	只允许增加内容


[root@news-static ~]# lsattr 2.txt
-------------e- 2.txt
[root@news-static ~]# chattr +i 2.txt
[root@news-static ~]# lsattr 2.txt
----i--------e- 2.txt
[root@news-static ~]# chattr -i 2.txt
[root@news-static ~]# lsattr 2.txt
-------------e- 2.txt
[root@news-static ~]#



[root@news-static ~]# chattr +a 2.txt
[root@news-static ~]# lsattr 2.txt
-----a-------e- 2.txt
[root@news-static ~]# echo 3 > 2.txt
-bash: 2.txt: 不允许的操作
[root@news-static ~]# echo 3 >> 2.txt
[root@news-static ~]# cat 2.txt
123
3
[root@news-static ~]#

9.遍历目录

shell 复制代码
[root@news-static mydir]# cat test.sh
#!/bin/bash

directory=$1

# 使用 find 命令递归遍历指定目录下的所有文件和子目录
find "$directory" -print | while read file; do
    if [[ -d "$file" ]]; then  # 判断是否为目录
        echo "Dire: $file"
    elif [[ -f "$file" ]]; then  # 判断是否为文件
        echo "File: $file"
    fi
done


[root@news-static mydir]# /tmp/mydir/test.sh /tmp/mydir
Dire: /tmp/mydir
File: /tmp/mydir/boge.sh
File: /tmp/mydir/test.sh
Dire: /tmp/mydir/dir1
Dire: /tmp/mydir/dir1/dir2
Dire: /tmp/mydir/dir1/dir2/dir3
File: /tmp/mydir/dir1/dir2/dir3/file3.log
File: /tmp/mydir/dir1/dir2/file2.log
File: /tmp/mydir/dir1/file1.log
[root@news-static mydir]#



[root@news-static mydir]# cat boge.sh
#!/bin/bash

listFile() {
  local tempDir=$1

# 使用 find 命令递归遍历指定目录下的所有文件和子目录
  find "$tempDir" -print | while read file; do
      if [[ -d "$file" ]]; then  # 判断是否为目录
          echo "Dir: $file"
      elif [[ -f "$file" ]]; then  # 判断是否为文件
          echo "Fil: $file"
      fi
  done
}
#运行函数
listFile $1


[root@news-static mydir]# /tmp/mydir/test.sh /tmp/mydir
Dire: /tmp/mydir
File: /tmp/mydir/boge.sh
File: /tmp/mydir/test.sh
Dire: /tmp/mydir/dir1
Dire: /tmp/mydir/dir1/dir2
Dire: /tmp/mydir/dir1/dir2/dir3
File: /tmp/mydir/dir1/dir2/dir3/file3.log
File: /tmp/mydir/dir1/dir2/file2.log
File: /tmp/mydir/dir1/file1.log
[root@news-static mydir]#

10.处理僵尸进程

生产案例:

zombie 僵尸进程的发现,查看,及解决的步骤

1、通过 top 查看是否存在zombie 僵尸进程

root@localhost \~\]# top top - 14:53:32 up 86 days, 9:47, 2 users, load average: 2.09, 1.91, 1.79 Tasks: 1248 total, 1 running, 1246 sleeping, 0 stopped, **1 zombie** Cpu(s): 16.5%us, 7.3%sy, 0.0%ni, 72.9%id, 3.1%wa, 0.0%hi, 0.2%si, 0.0%st 2、查看具体是哪个进程 \[root@localhost \~\]# ps -A -o stat,ppid,pid,cmd \| grep -e "^[1](#1)^" Z 2216 31127 \[abrt-server

3、查看僵尸进程是什么应用

root@localhost \~\]# lsof -p 2216 4、kill僵尸进程 \[root@localhost \~\]# kill -9 2216

11.shell并发快速查询在线IP

cat select_ip.sh

shell 复制代码
#!/bin/bash
#__author__: boge

#不在线ip记录
> ./ip_offline.txt


#在线ip记录
> ./ip_online.txt


#传入网段3个参数案例:	10.0.1 1 254
if [ $# -ne 3 ];then
	echo "Usage: bash $0 10.0.1 1 254"
	exit 3
fi

pingnum=`seq $2 $3`
for i in $pingnum
do
{
  ping -c 1 -i 0.1 -W 1 $1.$i &> /dev/null
  if [ $? -eq 0 ];then
    echo "IP:   $1.$i is online."
    echo "$1.$i" >> ./ip_online.txt
  else
    echo "IP $1.$i is offline."|tee -a ./ip_offline.txt
  fi
}&
done

#等待所有子进程返回结果后在退出主进程
wait

12.循环for和while

shell 复制代码
#for循环输出1到10的数字
[root@news-static ~]# for i in `seq 10`;do echo "$i";sleep 1;done


#无限循环输出
[root@news-static ~]# cat while.sh
#!/bin/bash

while true
do
  date
  sleep 1
done


#while 循环输出1到10的数字
[root@news-static ~]# cat while.sh
#!/bin/bash

counte=1

while [ $counte -le 10 ]
do
  echo $counte
  counte=$((counte + 1))
  sleep 0.5
done

11.shell中的列表和字典

shell 复制代码
-------------
SHELL数组(实现列表)
-------------
# family=(aaa bbb ccc)    <--- 定义数组
# echo ${#family[*]}     <--- 取数组里变量长度
3
# echo ${family[0]}     <--- 取数组第一个变量
aaa
# echo ${family[1]}     <--- 取数组第二个变量
bbb
# echo ${family[2]}     <--- 取数组第三个变量
ccc
# echo ${family[*]}     <--- 取数组里所有变量
aaa bbb ccc
# echo ${family[*]:2}     <--- 去掉数组里的前两个值,保持取最后一个值
ccc

脚本示例:
# vim test.sh
#!/bin/bash
family=(     # or 也可以这样定义  family=(aaa bbb ccc)
aaa 
bbb 
ccc
)

for name in ${family[*]}   #第一种方法,常规for循环取值的方式
do
echo $name
done
echo "================="
for ((name=0;name<${#family[*]};name++))   #第二种方法
do
echo ${family[name]}
done

执行结果:
[root@nfs-server scripts]# bash test.sh 
aaa
bbb
ccc
=================
aaa
bbb
ccc




实现"字典":

my_config=(
  shanghai+http://10.0.1.201+boge+devops1
  beijing+http://10.0.1.202+boge+devops2
  hongkong+http://10.0.1.203+boge+devops3
)


for r in `echo ${regions}`
do
  export MY_REGION=`echo ${my_config[@]}|tr " " "\n"|grep -w $r|awk -F+ '{print $1}'`
  export MY_URL=`echo ${my_config[@]}|tr " " "\n"|grep -w $r|awk -F+ '{print $2}'`
  export MY_USERNAME=`echo ${my_config[@]}|tr " " "\n"|grep -w $r|awk -F+ '{print $3}'`
  export MY_PASSWORD=`echo ${my_config[@]}|tr " " "\n"|grep -w $r|awk -F+ '{print $4}'`

  echo "====== $r START  ======"
  echo $MY_URL
  echo $MY_USERNAME
  echo $MY_PASSWORD
  echo $MY_REGION
  echo "====== $r END  ======"
done


# 另外一种实现字典的形式
#!/bin/bash


test='
{
  "aaa": 1,
  "bbb": 2,
  "ccc": 3
}
'

echo $test|jq -r ".aaa"

12.运维服务菜单选项

1. if elif else脚本

shell 复制代码
#!/bin/bash

# 这个脚本演示了如何使用 case 语句根据用户输入执行不同的操作

echo "请输入你的选择[1 - 4]:"
echo "1. 开始服务"
echo "2. 停止服务"
echo "3. 重启服务"
echo "4. 退出服务"

read choice

if [[ $choice -eq 1 ]];then
    echo "开始服务了"
elif [[ $choice -eq 2 ]];then
    echo "停止服务了"
elif [[ $choice -eq 3 ]];then
    echo "重启服务了"
else
    echo "退出服务了"
fi

2.使用case脚本:

shell 复制代码
#!/bin/bash

# 这个脚本演示了如何使用 case 语句根据用户输入执行不同的操作

echo "请输入你的选择[1 - 4]:"
echo "1. 开始服务"
echo "2. 停止服务"
echo "3. 重启服务"
echo "4. 退出服务"

read choice

case $choice in
    1)
        echo "Starting service..."
        # 执行启动操作的命令
        ;;
    2)
        echo "Stopping service..."
        # 执行停止操作的命令
        ;;
    3)
        echo "Restarting service..."
        # 执行重启操作的命令
        ;;
    4)
        echo "Exiting service..."
        exit
        ;;
    *)
        echo "Invalid choice"
        ;;
esac

13.标准的运维工具脚本

shell 复制代码
#!/bin/bash

# 这个脚本演示了如何使用 getopts 函数解析命令行参数
if [ $# -eq 0 ];then
    echo "Usage: bash $0 (-A|-D|-L) -e (1h or more) -t (admin|view) -u boge"
    exit 1
fi


# 默认值
ACTION=""
EXPIRY=""
USER_TYPE=""
USER_NAME=""

# 解析命令行参数
while getopts "ADLe:t:u:" OPTION; do
    case $OPTION in
        A)
            ACTION="add-test $1"
            ;;
        D)
            ACTION="del-test $1"
            ;;
        L)
            ACTION="list-test $1"
            ;;
        e)
            EXPIRY="$OPTARG"
            [[ $OPTARG =~ ^[1-9][0-9]*h$ ]] || { echo "'-e' must be set like '2h, 5h, 50000h, ...'"; exit 1; }
            ;;
        t)
            USER_TYPE="$OPTARG"
            [[ $OPTARG =~ ^(admin|view)$ ]] || { echo "'-t' can only be set as 'admin' or 'view'"; exit 1; }
            ;;
        u)
            USER_NAME="$OPTARG"
            ;;
        ?)
            echo "Invalid option: -$OPTARG"
            exit 1
            ;;
    esac
done

function add-test(){
# 打印解析的参数
echo "ACTION: $ACTION"
echo "EXPIRY: $EXPIRY"
echo "USER_TYPE: $USER_TYPE"
echo "USER_NAME: $USER_NAME"
}

function del-test(){
# 打印解析的参数
echo "ACTION: $ACTION"
echo "EXPIRY: $EXPIRY"
echo "USER_TYPE: $USER_TYPE"
echo "USER_NAME: $USER_NAME"
}

function list-test(){
# 打印解析的参数
echo "ACTION: $ACTION"
echo "EXPIRY: $EXPIRY"
echo "USER_TYPE: $USER_TYPE"
echo "USER_NAME: $USER_NAME"
}

${ACTION}

参考博客:博哥爱运维
https://www.toutiao.com/article/7271959603280265739?wid=1698656801777


  1. Zz ↩︎
相关推荐
Sheep Shaun12 小时前
如何让一个进程诞生、工作、终止并等待回收?——探索Linux进程控制与Shell的诞生
linux·服务器·数据结构·c++·算法·shell·进程控制
dingdingfish2 天前
Bash 学习 - 第1章:Introduction
bash·shell·programming·introduction
pr_note4 天前
legality检查
shell·tcl
啥都不懂的小小白5 天前
Shell脚本编程入门:从零基础到实战掌握
前端·shell
dingdingfish8 天前
GNU Parallel 学习 - 第1章:How to read this book
bash·shell·gnu·parallel
似霰11 天前
Linux Shell 脚本编程——核心基础语法
linux·shell
似霰12 天前
Linux Shell 脚本编程——脚本自动化基础
linux·自动化·shell
偷学技术的梁胖胖yo13 天前
Shell脚本中连接数据库查询数据报错 “No such file or directory“以及函数传参数组
linux·mysql·shell
纵有疾風起22 天前
【Linux 系统开发】基础开发工具详解:软件包管理器、编辑器。编译器开发实战
linux·服务器·开发语言·经验分享·bash·shell
gis分享者24 天前
Shell 脚本中如何使用 here document 实现多行文本输入? (中等)
shell·脚本·document·多行·文本输入·here