当前位置: 首页 > ai >正文

Linux系列-2 Shell常用命令收集

背景

本文用于收集Linux常用命令(基于Centos7),是一个持续更新的博客,建议收藏,编写shell时遇到问题可以随时查阅。

1.Shell类型

shell是用C语言编写的程序,作为命令解释器连接着用户和操作系统内核。常见的shell有sh(Bourne Shell), csh(C-Shelll), ksh(Korn Shell), bash(Bourne Again Shell), 推荐使用bash(易用和免费).
通过cat /etc/shells可以查看系统支持的shell类型:
在这里插入图片描述
可在shell脚本顶部指定使用的shell类型,如下表示使用bash类型:

#!/bin/bash#获取当前目录
current_dir=$(cd `dirname $0`;pwd)

2.shell变量类型

shell中常用的变量类型有字符串、数值、数组类型; shell中没有布尔类型, 零值表示 false,非零值表示 true。

2.1 数值类型

数值包括浮点和整数类型,shell不支持浮点数计算,需要借助三方库bc进行( yum -y install bc )。
[1] 运算
在shell中所有的变量类型默认是字符串类型,因此不能直接计算, 可通过expr表达式进行:

#expr形式,`expr $A + &B`
echo `expr $a + $b`
#说明:+-\* / % (*表示乘号,但是作为通配符,需要使用\转义);运算符左右需要有空格。

$变量或者${变量}用于提取变量的值,但是不能执行表达式,反引号``用于执行表达式并获取结果:

[root@localhost ~]# echo The date is `date`
The date is 2025年 05月 28日 星期三 23:10:43 CST[root@localhost ~]# echo ${date}#返回空,将date当做变量来提取值

[2] 比较

# ==比较数字是否相等,!= 表示不相等;
a=0
b=1
if  [ $a == $b ] ; then echo "yes" ;else echo "no" ;fi;
if  [ $a != $b ] ; then echo "yes" ;else echo "no" ;fi;[]< > >= <=等需要使用转义,而[[]]中不需要转义
[ $a < $b ] 等价于 [[ $a  < $b ]]

注意:
(1)[] 和运算符左右两侧必须有空格
(2)可以在一行中写多条shell命令,使用分号分隔
(3)使用#进行单号注释

# 使用关系运算符:
#-eq 相等, -ne不等;  -gt大于, -lt小于;  -ge大于等于, -le小于等于
if [ $A -eq $B]
thenecho "相等"
elseecho "不相等"
fi

注意:关系运算符的应用范围只支持数值类型,不支持字符串。
在[]或[[]]中可以使用单等号和双等号进行字符串和整型是否相等的判断,但是建议使用-eq等关系运算符。

if  [ $a = $b ] ; then echo "yes" ;else echo "no" ;fi;if  [[ $a = $b ]] ; then echo "yes" ;else echo "no" ;fi;

2.2 字符串类型

可以使用单引号和双引号、不用引号表示;单引号不会替换内容,全样输出,双引号会进行变量替换。

shell中没有空类型,未定义的变量默认表示长度为0的字符串,即空字符串。

可以使用 ==!= 来表示是否相等;

[ -z $a ] a的长度为0时返回true;  [ -n $a ] a的长度不为0时返回true
[ $a ] 不为空时返回true;

echo ${#a} 用于计算字符串长度

2.3 数组类型

shell中仅支持一维数组,下标从0开始,使用小括号进行包裹,并用空格对元素进行分隔。

# 数组定义
test_arr=(aa 123 bb "") # 使用下标从数组中取值
echo ${test_arr[0]}# 获取数组长度(*或者@表示全部元素,#表示取长度)
${#test_arr[*]} 或者${#test_arr[@]} # 取数组中全部元素(删除#即可)
${#test_arr[*]} 或者${#test_arr[@]} 

数组的遍历方式:

test_arr=(a b c 1 2 3 "")
for i in ${test_arr[*]}; do echo $i;done

3.test 表达式

test表达式等价于[], 与[[]]在写法上略有不同;都能实现对数值、字符串类型进行判断,以及对文件的非空、大小、属性等进行判断。
使用逻辑运算符时略有不同:

#  []中只能使用 -a和-o和!     
#  [[]] 中只能使用 && || 和! 
[ expression1 -a expression2 ] 等价于 [ expression1 && expression2 ] 
[ expression1 -o expression2 ] 等价于 [ expression1 || expression2 ] 
[ !expression2 ] 等价于 [[ !expression1 ]] 

文件类型:

-e 是否存在;
-f 普通类型(存在且); -d目录(存在且);
-b块设备(存在且); -c字符设备(存在且);
-S套接字(存在且); -L链接(存在且)

文件属性:

-r 可读(存在且);-w可写(存在且);-x可执行(存在且)

案例:

#[]方式
if [ ! -e test1.txt ];                 then echo "yes" ;else echo "no"; fi
if [ ! -e test1.txt -a -e test2.txt ]; then echo "yes"; else echo "no"; fi#[[]]方式
if [[ (-e test1.txt && -e test2.txt) ]];   then echo "yes" ;else echo "no"; fi
if [[ !(-e test1.txt && -e test2.txt) ]];  then echo "yes" ;else echo "no"; fi
if [[ ! (-e test1.txt && -e test2.txt) ]]; then echo "yes" ;else echo "no"; fi
#在[[]]中可通过()改变表达式的优先级
#注意! && || 与表达式之间必须有空格

4.函数定义和使用

4.1 函数定义和传参

函数的定义要优先于函数的调用,函数定义有如下两种方式:

#方式1
function 函数名(){#函数体
}#方式2
函数名(){#函数体
}

函数内部可以通过$符号进行变量的获取,有以下类型:

$$ 获取当前进程号;
$0 获取当前所在文件名;
$1-n 按顺序获取参数(注意索引从1开始);
$# 获取参数长度;
∗ 和 * 和 @ 获取全部参数

函数调用时直接使用函数名即可,不需要添加括号,传参以逗号进行分隔。

function add() {echo "dollar0 is $0"echo "dollar1 is $1"echo "dollar2 is $2"echo "dollar# is $#"echo "dollar* is $*"echo "dollar@ is $@"echo "dollar-dollar is $$"
}add a b

执行结果如下:
在这里插入图片描述

4.2 函数的返回值

当函数没有通过return语句显示返回时,使用最后一条语句的执行结果返回:执行成功返回0,否则返回1。
也可以在函数中通过return语句显示返回结果,但是只能返回[0-255]之间的整数(否则按256取模),在调用函数结束后使用$?获取执行结果。

function add() {return 100
}
add
echo "result is $?"

还可通过标准输出流返回结果,函数内部通过echo将要返回的结果输出到标准输出流,在调用函数的地方使用反引号或者$()进行获取,如下所示:

#!/bin/bashfunction sum_int(){local result=0for n in $@do((result+=n))doneecho $resultreturn 0
}echo $(sum_int 1 2 3 4 5)

4.3 使用其他脚本中定义的函数

将文件定义为sh或者其他文件类型(如.conf),使用 . 路径或者使用source 文件名的形式引入。

#test.conf文件
function add() {return 0
}##test.sh文件
. ./test.conf #或者 source test.conf
add #调用引入的函数

5.全局变量和局部变量和环境变量

5.1 变量定义与提取

# 定义
a=1
b="abc"# 提取
echo $a
echo ${a}

注意:等号左右不能有空格。

5.2 shell脚本内的全局变量与局部变量

shell脚本中默认为全局变量,如:

aa='123'
echo "aa is $aa"
function test(){echo "[function]aa is $aa"bb='234'
}test
echo "bb is $bb"

得到结果如下:

[root@localhost sy]# sh test_global.sh
aa is 123
[function]aa is 123
bb is 234

无论是在全局范围定义的变量a还是在方法内部定义的变量b,在当前整个shell脚本中有效。

一般而言,为了防止变量污染,会将方法内的变量通过local关键字定义为局部变量,
使得定义的变量仅在函数块内部有效。案例如下:

function test(){aa='123'local bb='234'
}test
echo "aa is $aa"
echo "bb is $bb"

结果如下:

[root@localhost sy]# sh test_local.sh
aa is 123
bb is

其中a为全局变量,b为方法内部的局部变量,此时在方法外的不可见,$b获取的结果为空。

5.3 环境变量

介绍环境变量之前,有必要简要介绍一下登录方式以及环境变量配置文件。

环境变量配置文件:
centos中环境变量的配置文件有两类:全局配置文件与用户配置文件。
全局配置文件对应: /etc/profile
用户配置文件按优先级:~/.bash_profile > ~/.bash_login > ~/.profile. 按顺序查找并执行,且仅执行第一个。

登录方式:

通过用户名新建一个shell远程连接,连接时,会按照先后顺序依次执行加载全局配置文件和用户配置文件;
当通过切换shell或者使用su切换用户时,不会加载配置文件。
当通过 su - 命令模拟登录来切换用户时,会按照先后顺序依次执行加载全局配置文件和用户配置文件。

5.3.1 所有shell有效

一个shell窗口修改/etc/profile文件保存后(如添加一个变量a=1),执行source /etc/profile在当前shell生效。
新开shell窗口时,由于会自动执行source /etc/profile,从而可以读取变量a的值为1;
对于已经打开的shell窗口,需要再次执行source /etc/profile.

上述配置不区分用户,如果需要对指定用户生效,需要修改用户配置文件,如~/.bash_profile

5.3.2 export关键字

默认情况下,环境变量(无论是全局还是用户)仅对主进程有效,可通过export进行暴露,对全部子shell和子进程有效,案例如下所示:

[step1]/etc/profile中添加如下两行变量定义:

export NAME1=sys1
NAME2=sys2

[step2] 执行source /etc/profile使得改动生效:

source /etc/profile

[step3] 主进程查看变量:

[root@localhost sy]# echo $NAME1
sys1
[root@localhost sy]# echo $NAME2
sys2

[step4] 切换用户并查看变量:

[root@localhost sy]# su centuser
[centuser@localhost sy]$ echo $NAME1
sys1
[centuser@localhost sy]$ echo $NAME2[centuser@localhost sy]$

此时,NAME2不可见,而通过export暴露的NAME1可见。

注意:不仅仅是切换用户,切换shell或者创建的子进程机制相同。

除了环境变量,其他变量也是如此:父进程定义的变量默认对子进程不可见,可通过export进行暴露:

[centuser@localhost sy]$ test_a='aa'
[centuser@localhost sy]$ export test_b='bb'
[centuser@localhost sy]$ sh
sh-4.2$ echo $test_ash-4.2$ echo $test_b
bb

6.if结构和case结构

6.1 if结构

#1.if
if 表达式; then#逻辑
fi#2.if-else
if 表达式; then#逻辑1
else#逻辑2
fi#3.if-elif-fi
if 表达式1; then#逻辑1
elif 表达式2; then#逻辑2
else#逻辑3
fi

6.2 case结构

case VAR invar1) command1 ;;var2) command2 ;;var3) command3 ;;*) command-default;;
esac

注意:shell中的case不存在穿透问题

案例介绍:

case "$1" in"restart")echo "restart success";;"stop")echo "stop success";;"start")echo "start success";;*)echo "parameter error!! ";echo "three parameters are valid----restart, start, stop";;
esac

7.for和while循环结构

7.1 for循环结构

for 变量名 in 取值列表
do命令
done#{1..5}为取值范围1到5
for i in {1..5};do echo $i;done
for((i=1;i<=5;i++));do echo $i;done#遍历数组:
test_arr=(1 2 3 4 5)
for i in ${test_arr[*]}; do echo $i;done

7.2 while循环结构

#当条件测试成立(条件测试为真),执行循环
while  条件测试
do循环体
donei=1
while [ $i -le 10 ]
doecho $ilet i++
done

8.文件操作

8.1 创建文件和文件夹

#创建文件
touch 文件名
> touch a.txt# 创建文件夹: 如果文件夹已存在或者某一路径不存在,报错
mkdir 文件夹
>mkdir dira
>mkdir /home/test/dira#递归创建文件夹,如果文件夹或者某一路径不存在创建,存在则不创建(不报错)
mkdir -p 文件夹
>mkdir -p /home/test/dira

8.2 编辑、复制、移动、删除

8.2.1 文件编辑与查询

可以通过vi与vim对文件进行编辑,推荐vim.

#显示行号
:set nu#不保存修改退出
:q!#保存并退出
wq!#根据关键词从底部开始向上搜索,按N或者shift+N进行定位
? 关键词#i或者insert键可以将非编辑状态切换至编辑状态(插入和替换)#非编辑状态下:"dd"删除一行;"d+数字N+回车"删除N行

8.2.2 复制

cp命令的参数:

-r 表示递归操作, 适用于进行目录复制;

-p 保留元属性,如 修改时间、访问时间和权限模式;

#1.复制文件
cp source_dir dest_dir#2.复制目录
cp -r source_dir  dest_Dir#3.复制多个文件或文件夹
cp -r source_dir/*  dest_Dir

8.2.3 移动

# 修改名称
mv 源文件 目标文件
>mv a.txt b.txt# 移动路径,不替换名称
mv 源文件 路径/
>mv a.txt /home/test/# 移动路径&&替换名称
mv 源文件 路径/目标文件
>move a.txt /home/test/b.txt

8.2.4 删除

# 删除文件或文件夹
rm 文件
>rm a.txt# 删除文件夹(递归删除文件夹文件)
rm -r 文件夹
>rm -r /home/test# 强制删除文件或文件夹(不会交互提示-是否删除)
rm -rf 文件/文件夹
>rm -rf /home/test

8.3 压缩与解压缩

zip类型的压缩和解压缩:

#压缩文件
[root@localhost test]# zip test.zip test.txtadding: test.txt (stored 0%)#递归压缩文件夹
[root@localhost home]# zip -r test.zip /home/test/adding: home/test/ (stored 0%)adding: home/test/test.txt (stored 0%)adding: home/test/test.zip (stored 0%)adding: home/test/test1.txt (stored 0%)adding: home/test/test2.txt (stored 0%)adding: home/test/test3.txt (stored 0%)#zip压缩时会携带路径,因此可通过相对路径进行压缩。
#比如:对路径下所有文件进行打包(解压时-不会携带路径)
[root@localhost test]# zip -r test.zip ./
updating: test.txt (stored 0%)adding: test1.txt (stored 0%)adding: test2.txt (stored 0%)adding: test3.txt (stored 0%)#解压当前路径下的zip包到当前文件夹
unzip test.zip#解压其他路径的zip包到当前文件夹
unzip /home/test.zip

tar类型的压缩和解压缩:

## =================使用 -zcvf 压缩=================
# 携带路径压缩
[root@localhost test]# tar -zcvf test.tar.gz /home/test
tar: Removing leading `/' from member names
/home/test/
/home/test/test.txt
/home/test/test1.txt
/home/test/test2.txt
/home/test/test3.txt
tar: /home/test: file changed as we read it# 不携带路径压缩,如对当前路径进行打包
[root@localhost test]# tar -zcvf test.tar.gz ./
./
./test.txt
./test1.txt
./test2.txt
./test3.txt
tar: .: file changed as we read it## =================使用 -zxvf 解压缩=================
# 解压缩当前路径下的test.tar.gz包到当前路径
tar -zxvf test.tar.gz# 解压缩home/sheng路径下的test.tar.gz包到当前路径
tar -zxvf /home/sheng/test.tar.gz

9.属组和权限操作

通过ls或者ll可以查看文件的属组和权限信息,如下所示:

[root@localhost test]# ll -t
total 4
-rwxrw-r--. 1 root root 4 May 29 11:10 test.txt

此时,test.txt的属组为root:root, 文件权限为rwxrw-r–.

其中:rwxrw-r–按照三个一组按顺序分别表示当前用户(rwx),群组内用户(rw-),其他用户(r–); 此时当前用户可读可写可执行,群组内用户可读可写不可执行,其他用户可读不可写不可执行。

rwx也可以用位进行表示,r表示4,w表示2,x表示1;则rwx=7,rw-=6,r-x=5,r–=4.

对于目录而言,权限与文件略有不同:
目录如果没有执行权限,则无法cd切换到该目录,且该目录以及递归子目录与文件都没有任何权限(通过ls+全路径查询也不行); 如果没有可写权限,则无法在目录下创建/删除文件或者文件夹;如果没有可读权限,无法获取目录下文件或文件夹的信息,但是不影响执行与修改。

另外,可通过修改umask修改系统的默认权限,当创建文件时,系统将使用修改后的默认权限。

[root@localhost test]# umask
0022

此时,umask权限掩码为022,则默认创建的文件夹的权限为755( 777-022=755),即rwxr-xr-x;

文件由于默认不具备执行权限,扣除执行权限,为rw-r–r–

修改umask掩码为020后创建文件,查看文件的默认权限:

[root@localhost test]# umask 020
[root@localhost test]# umask
0020[root@localhost test]# touch a.txt
[root@localhost test]# mkdir dirb
[root@localhost test]# ll
total 0
-rw-r--rw-. 1 root root 0 May 29 14:54 a.txt
drwxr-xrwx. 2 root root 6 May 29 14:54 dirb

此时,文件的默认权限为(777-020=757), 即目录默认权限为rwxr-xrwx,文件默认权限为rw-r–rw-

9.1 修改属组

#修改文件属组"chown 用户:群组 文件名"
chown test:test a.txt# 递归修改文件夹内所有文件的属组
chown -R test:test /home/test

9.2 修改权限

可对文件进行读、写、执行权限的添加和删除;

# 对test.sh文件(所有用户)添加可执行权限
chmod +x test.sh# 仅对当前用户添加可执行权限(u表示所属用户,g表示群组,o表示其他用户)
chmod u+x test.sh#还可通过数字进行权限修改
chmod 777 test.sh#-R 对文件夹递归修改权限
chmod -R 777 test.sh

10.kill

kill指令用法如下:

kill [signal] PID#pid是进程的ID
#signal一般有TERM(默认), KILL(-9), INT(-2), STOP(-17), CONT(-18)#常用的方式有
kill pid #向进程pid发送TERM信号,请求进程正常退出,进程可以在完成清理工作后退出;kill -9 pid #向进程pid发送KILL信号,强制进程退出,可能导致数据丢失和文件损失问题

11.常用工具函数

11.1 properties文件读取

version.properties文件如下:

aiws.versionCode=1.0

对应提取方法如下:

propvalue()
{grep ${1} $project_dir/version.properties | cut -d'=' -f2 | sed 's/\r//'return $?
}version_code=$(propvalue aiws.versionCode)

12.常见指令

其他常见执行sleep、awk、sed、expr、exec、dirname…等的用法将陆续更新。

http://www.xdnf.cn/news/9715.html

相关文章:

  • fingerprint2浏览器指纹使用记录
  • Spring框架学习day4--Spring集成Mybatis(IOC)
  • Vue 3 的路由管理
  • 小白成长之路-Linux日志管理
  • [MMU]IOMMU的主要职能及详细的验证方案
  • 3 分钟学会使用 Puppeteer 将 HTML 转 PDF
  • Axure设计案例——科技感渐变线性图
  • 不可变集合类型转换异常
  • Astra学习之-如何修改Header-logo和favicon图标
  • Linux | Shell脚本的基础知识
  • 基于ubuntu安装hadoop
  • .NET8入门:14.ASP.NET Core MVC进阶——Model
  • 前端高频面试题1:HTML/CSS/浏览器/计算机网络
  • 安装 Node.js 和配置 cnpm 镜像源
  • Java异常处理的全面指南
  • 基于通义千问的儿童陪伴学习和成长的智能应用架构。
  • Spring AI 之对话记忆(Chat Memory)
  • [网页五子棋][匹配模块]处理开始匹配/停止匹配请求(匹配算法,匹配器的实现)
  • python h5py 读取mat文件的<HDF5 object reference> 问题
  • StarRocks x Iceberg:云原生湖仓分析技术揭秘与最佳实践
  • 【大模型】Bert变种
  • Kubernetes资源申请沾满但是实际的资源占用并不多,是怎么回事?
  • 微深节能 码头装卸船机定位与控制系统 格雷母线
  • WPF 按钮悬停动画效果实现
  • 【五模型时间序列预测对比】Transformer-LSTM、Transformer、CNN-LSTM、LSTM、CNN
  • 《AI大模型的开源与性能优化:DeepSeek R1的启示》
  • 互斥锁、自旋锁、读写锁、悲观锁、乐观锁的应用场景
  • 深入理解C#中的LINQ:数据查询的终极利器
  • 2013-2021年各省电子商务数据
  • 认识多系统萎缩:一种隐匿进展的神经退行性问题