《Linux 系统命令及Shell脚本实践指南》

Linux 系统命令及Shell脚本实践指南

《Linux 系统命令及Shell脚本实践指南》

该书从结构上分为三部分:

主要侧重于应用实操,是一本实践指南。通读本书,我觉得不足之处就是没有展示内存管理部分。

第一部分

为第一章到第八章,为基础内容,详细的介绍了Linux的历史发展、

安装使用、用户管理、文件管理、文件系统、字符处理、网络管理、进程管理和软件安装

查看命令用法

man 命令名称 如果该命令说明文档很长:输入man 页数 命令名称

命令名称 --help

查看内建命令 help -d

命令替换$() 、``,所谓 命令替换就是可以执行命令的

两者相比,前者可读性更强,支持命令嵌套:如:result=(command1 (command2))

命令取别名:alias ll='ls -la'

1.1Linux的历史发展

免费、开源、1991年由芬兰大学生编写的Minix延伸而来,这位大学生就是后来的Linux之父【Linus Torvalds】

1.2用户管理

查看用户:users、who、w

调查用户:finger 用户名

切换用户:su【普通用户使用】和sudo【超级用户使用,即root用户】使用root用户的权限进行操作

增删改查用户、用户组

1.3任务管理

单一时刻执行一次任务使用at
周期性任务使用:cron表达式,命令crontab

crontab -e 编辑

crontab -l 查看

crontab -r 删除

1.4文件管理

相对路径:如./ 【表示在当前目录下】和.../【表示在当前目录的上一级目录】

touch 文件名 【创建文件】

rm 文件名 【删除文件remove】--》rm -rf /test/myfile/*【-rf是敏感操作,慎用】

mv 文件名 目录/新的文件名【移动或重命名文件】

如果第二个参数是目录,表示移动:如 mv 1.txt /myfile/test

如果第二个参数是文件名,表示重命名:如 mv 1.txt myNewName.txt

如:mv 1.txt /myfile/test/myNewName.txt【移动到指定文件夹下同时重命名】

cat -n 文件名【查看文件】

head/tail -n 要查看的行数 文件名,如 tail -n 1000 文件名

实时查看文件尾:tail -f 文件名 【或文件的全路径】

cp 1.txt 111.txt【复制文件】

cp 1.txt /myfile/test/111.txt【复制文件且重命名】

cp 1.txt /myfile/test/【复制文件但不重命名】

复制目录也是使用 cp 命令 但是需要使用 -r参数 否则不生效 如:cp -r aa bb

切换目录:cd ,

查看目录中的文件列表 ls -la ,

创建目录 mkdir -p 目录名

查看当前目录 pwd

1.4.1 Linux shell 文件名中的通配符

在Linux的Shell中,通配符是一种用于匹配文件名的特殊字符。

它们可以帮助你在命令中指定一组文件名模式,以便进行文件操作。以下是一些常用的通配符及其用法:

  1. 星号(*):匹配任意字符(包括空字符)的任意长度。例如,*.txt可以匹配所有以.txt结尾的文件名。

  2. 问号(?):匹配任意单个字符。例如,file?.txt可以匹配类似于file1.txt、file2.txt等的文件名。

  3. 方括号(\[\]):匹配方括号中列出的任意一个字符。例如,file123.txt可以匹配file1.txt、file2.txt或file3.txt。

  4. 范围(-):在方括号中使用范围来匹配一定范围内的字符。例如,filea-z.txt可以匹配以file开头、后面跟着任意小写字母、最后以.txt结尾的文件名。

  5. 反向范围(\^):在方括号中使用反向范围来匹配不在范围内的字符。

    例如,file\^0-9.txt可以匹配以file开头、后面跟着任意非数字字符、最后以.txt结尾的文件名

    这些通配符可以与命令一起使用,如ls、cp、rm等,以匹配符合特定模式的文件名。你可以根据需要使用不同的通配符来进行文件操作

1.5 改变文件权限 chmod

分别用user、group、others 来代表文件拥有者、拥有组、其他人的权限,简写 u、g 、o

分别使用r、w、x来代表 读、写、和执行权限

定义r用数字4表示,w用数字2表示,x用数字1表示。

假如我们想设置一个文件的权限是:

拥有者的权限是:读写执行 【rwx】则数字表示为7,拥有组的权限是读、执行 【r-x】则数字表示为5,其他人的权限是只读【r- -】则数字表示为4

就可以使用命令 chmod 754 文件名,来表示,如果需要赋予拥有者、拥有组、其他人的权限都具有读写执行,可以使用chmod 777 文件名

为该目录下所有的文件及其子目录设置权限使用-R参数

chmod -R 777 文件名

1.6网络管理

ping

ifconfig

1.7进程管理

ps -ef |grep java 【查看java相关进程】

lsof【list open file 】

top 【相当于window中的资源管理器】,而ps是进程快照

kill -9 进程id号

1.8 查看内存使用情况

free -h

free -m

1.9 查看磁盘空间

df -h

第二部分

第二部分是本书的第九章到第十章,为编辑部分。

内容为Linux下常用的vi和vim的用法和基于流处理的sed和awk工具。这是管理Linux的基本技能。

vi 文件名 或者 vim 文件名

按 a或i 进入编辑模式,按esc键退出编辑模式,在英文模式下,按:wq保存并退出

查找模式

进入文件内容后,

使用/从头开始查找,输入要查找的字符串,按回车即可查找,按n下一个,按shift+n 查找上一个

使用?从尾部开始查找

基于流处理的sed,处理行

Linux sed 命令是利用脚本来处理文本文件。

sed 可依照脚本的指令来处理、编辑文本文件。

Sed 主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等。

shell 复制代码
# g 标识符表示全局查找替换,使 sed 对文件中所有符合的字符串都被替换,修改后内容会到标准输出,不会修改原文件:
sed -e 's/oo/kk/g' 文件名

基于流处理的awk,处理列

AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。

之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。

shell 复制代码
# 每行按空格或TAB分割【默认】,输出文本文件中的第一列和第四列
awk '{print $1,$4}' log.txt

# 使用awk -F  #-F相当于内置变量FS, 指定分割字符,指定使用逗号分割
awk -F, '{print $1,$2}'   log.txt

第三部分

第三部分为本书的第十一章到第十八章,为shell编程部分。

第一部分和第二部分都是为了给第三部分做铺垫,只有有了前面两个部分的基础,编写shell脚本才能得心应手。

内容包括shell的安装、使用、语法,其中最后一章是第三部分的重点,该章所有的脚本在实际应用中有很高的使用率。

shell 作为一门脚本编程语言,既然是编程语言,就会有变量、转义引用、运算符、特殊字符、if/elif/else、case等逻辑判断结构、

有for、while等循环语句,最后加上函数和输入输出重定向。

定义变量、数组

shell 复制代码
#!/usr/bin/env bash
# 查找bash 所在位置:
whereis bash
echo 'hello  world!'
# 定义变量,等号前后不能有空格
your_name="ljh"
echo '使用双引号拼接'
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting  $greeting_1

echo '使用单引号拼接'
greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !'
echo $greeting_2  $greeting_3

echo "ddd长度是:${#greeting_2}"

echo "截取后的字符串是:${greeting:1:4}"

str="xk is a great site"
echo `expr index "$str" io`  # 输出 4:

echo "用括号来表示数组,数组元素用\"空格\"符号分割开"
arr=(1 2 3 4 5 6)

echo "打印数组中的所有元素:${arr[@]}"

echo "打印数组中的第一个元素:${arr[0]}"

# 取得数组元素的个数
echo "取得数组元素的个数 ${#arr[@]}"
# 或者
echo "取得数组元素的个数 ${#arr[*]}"

echo "多行注释【:<<注释标识符】,例如:这里的注释标识符是remark 可以替换成其它字符:rem等"
:<<remark
  我是小孩也是王
  我是
  我
remark

echo "多行注释2"
:<<rem
  我是小孩也是王
  我是
  我
rem

echo "Shell 传递参数实例!例如执行:./my.sh 我是 小孩 也是王";
echo "美元符0表示文件名 执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";

echo "脚本参数的个数是:$#"

echo "脚本参数的所有元素是:$*"

echo "脚本运行的进程id号是:$$"

echo "上一个命令是否执行成功:$?"

echo "shell 使用的当前选项:$-"

echo "查询最后10条历史命令 history | tail -n 10"

#数值计算
echo "$((1+1))"
echo "$[1+1]"
#命令替换 $(),可以执行命令,将命令执行后的结果赋值给变量
echo "$(ls -la)"

测试结构 test 或者

如果使用 判断,\[\]里里外外都要有空格

逻辑测试

-a 表示且关系

-o 表示或关系

! 表示非

()表示优先级

字符串测试

【所有的字符变量都要加双引号"$string1"】

test -n 字符串

字符串长度非0

test -z 字符串

字符串长度为0

test 字符串 = 字符串2

测试字符串是否相等

test 字符串 != 字符串2

测试字符串不相等

字符串的比较

在Shell中,用于字符串比较的运算符是=而不是==。==运算符通常在条件语句中用于字符串比较,但它是Bash Shell的扩展语法,不是标准的Shell语法。

在标准的Shell语法中,应该使用=运算符来进行字符串比较。以下是使用=运算符进行字符串相等判断的示例:

shell 复制代码
if [ "$string1" = "$string2" ]; then
    # code to be executed if strings are equal
fi


#请注意,在使用=运算符进行字符串比较时,变量应该用双引号括起来,以避免在比较时出现意外的结果。如果你在标准的Shell环境中,并且需要进行字符串比较,请使用=运算符而不是==运算符 

#当在字符串比较时,如果没有将变量用双引号括起来,可能会导致以下情况下的意外结果:
#1. 空字符串问题:如果变量的值为空字符串,而在比较时没有使用双引号括起来,可能会导致语法错误或比较结果不符合预期
#提示的错误为 -bash: [: =: unary operator expected
string1=""
string2="hello"
if [ $string1 = $string2 ]; then
   echo "Strings are equal"
else
   echo "Strings are not equal"
fi

#2. 包含空格或特殊字符问题:如果变量的值包含空格或特殊字符,而在比较时没有使用双引号括起来,可能会导致比较结果不符合预期。
#提示的错误为 -bash: [: too many arguments
string1="hello world"
string2="hello"
if [ $string1 = $string2 ]; then
  echo "Strings are equal"
else
  echo "Strings are not equal"
fi
bash 复制代码
#判断两个字符串是否相等
#1. 使用=运算符:
  if [ "$string1" = "$string2" ]; then
		echo "Strings are equal"
  fi

#2. 使用==运算符(Bash特有):
  if [ "$string1" == "$string2" ]; then
		echo "Strings are equal"
  fi

#3. 使用双方括号[[ ]]结构(Bash特有):
  if [[ "$string1" = "$string2" ]]; then
		echo "Strings are equal"
  fi

#4. 使用test命令:
  if test "$string1" = "$string2"; then
		echo "Strings are equal"
  fi

#这些方式都可以用于判断两个字符串是否相等。需要注意的是,字符串变量应该用双引号括起来,以避免在比较时出现意外的结果。选择适合你的Shell环境和编码风格的方式来进行字符串相等的判断
数值测试【可以使用 \[ ]、(( ))】

-eq【相等】 、-ne【不等于】 、-gt【大于】、-ge【大于等于】、-lt【小于】、-le【小于等于】

文件测试

-e 文件是否存在

-f 是否是普通文件

-d 是否是目录

if/elif/else

bash 复制代码
if condition1
then
    command1
elif condition2 
then 
    command2
else
    commandN
fi

# 示例
a=10
b=20
if [ $a -ge $b ]
then
   echo "a 等于 b"
elif [ $a -gt $b ]
then
   echo "a 大于 b"
elif [ $a -lt $b ]
then
   echo "a 小于 b"
else
   echo "没有符合的条件"
fi


# 如果使用 ((...)) 作为判断语句,大于和小于可以直接使用 > 和 <。
a=10
b=20
if (( $a == $b ))
then
   echo "a 等于 b"
elif (( $a > $b ))
then
   echo "a 大于 b"
elif (( $a < $b ))
then
   echo "a 小于 b"
else
   echo "没有符合的条件"
fi

case...esac

bash 复制代码
case 值 in
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
esac


echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum #从键盘中读取数字
case $aNum in
    1)  echo '你选择了 1'
    ;;
    2)  echo '你选择了 2'
    ;;
    3)  echo '你选择了 3'
    ;;
    4)  echo '你选择了 4'
    ;;
    *)  echo '你没有输入 1 到 4 之间的数字'
    ;;
esac

for/while

bash 复制代码
# for循环格式
# 当变量值在列表里,for 循环即执行一次所有命令,使用变量名获取列表中的当前取值。
#命令可为任何有效的 shell 命令和语句。in 列表可以包含替换、字符串和文件名。
#in列表是可选的,如果不用它,for循环使用命令行的位置参数。
# for each 形式
for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done

#示例
for i in {2,4,6,8};
do 
	echo "$i";
done
# 1到10
for i in {1..10};
do 
	echo "$i";
done
# 前缀
for i in user{1..10};
do 
	echo "$i";
done
# 写成一行
for i in {2,4,20};do echo $(($i*3));done

sum=0;
for i in {1..10};do let sum+=$i;done

for i in `ls`;do echo "$i";done

for i in *.txt;do echo "$i";done

for i in `seq 1 2 10`;do echo "$i";done

# fori 形式
for (( exp1; exp2; exp3 )); 
do 
    COMMANDS; 
done

# 示例
sum=0;
for ((i=1;i<=10;i++));do let sum+=$i;echo "$sum";done


while COMMANDS; 
do 
	COMMANDS;
done

#示例1
num=10
while [ $num -gt 0 ]
do
    echo $num;
    num=$((num-1));
done
#示例2 注意写法上的区别,((...))中可以直接使用大于小于等比较符,而无需使用
# -eq【相等】 、-ne【不等于】 、-gt【大于】、-ge【大于等于】、-lt【小于】、-le【小于等于】
num=10
while (($num > 0))
do
    echo $num;
    num=$((num-1));
done

#批量创建用户
count=1
while [ $count -le 5 ]
do
    userName="user$count"
    useradd $userName
    echo "User $userName created."
    count=$((count+1))
done

函数

bash 复制代码
# 定义函数
 function myFunc () { 
 	echo "haha";
 }  
#调用函数
myFunc

# 定义函数
function resultOfSum(){
let c=${1}+${2}
 echo ${c}
}
# 调用带参函数
resultOfSum 1 2


function add(){
        sum=$[$1 + $2]
        #echo "sum="$sum
        #return "sum="$sum  # 自定义函数的return只能返回整数
        echo $sum
}
read -p "请输入第一个整数:" a
read -p "请输入第二个整数:" b
sum=$(add $a $b)
echo "sum="$sum

其它

多行输入

在大多数情况下,Shell脚本中的命令和语句都可以通过换行符进行分隔,而不需要使用分号。分号主要用于在同一行上写多个命令或语句

使用反斜杠(\):你可以使用反斜杠来继续输入下一行

bash 复制代码
   command \
   command1 \
   command2 \
   command3 

shell中的计算

在Linux的Shell中,有一些命令和操作符是用于计算的。以下是一些常用的计算命令和操作符:

  1. expr命令:用于执行基本的算术和字符串操作。它可以进行加法、减法、乘法、除法和取模等运算。例如:

result=$(expr 5 + 3)

echo $result

  1. let命令:用于执行算术运算和赋值操作。它支持基本的算术运算符(如+、-、*、/、%)和逻辑运算符(如&&、||、!)。例如:

let result=5+3

echo $result

  1. $(( ))操作符:用于执行算术运算。它支持基本的算术运算符和逻辑运算符,并且可以嵌套使用。例如:

result=$((5 + 3))

echo $result

  1. bc命令:用于执行高级数学运算,如平方根、指数、对数等。它支持数值计算和数学函数。例如:

result=$(echo "sqrt(16)" | bc)

echo $result

bc命令除了可以在命令行中执行数学计算,还可以进入终端交互模式,允许用户逐行输入数学表达式进行计算。例如:

bc 5 + 3

  1. \[\]操作符:是一种旧式的算术运算符,用于执行基本的算术运算。它类似于(( ))操作符,用于计算数学表达式并返回结果

    然而,需要注意的是,\[\]是一种旧式的语法,不如(( ))操作符常用。在现代的Shell环境中,推荐使用$(( ))操作符来进行算术运算,因为它更易读和易于理解

result=$5 + 3

echo $result

这些命令和操作符可以帮助你在Shell脚本中进行基本的算术和数值计算。你可以根据具体的需求选择适合的命令或操作符来进行计算

shell中 ,\[\] 和\[ ]的区别是什么?

在Shell中,\[\]和\[]是用于条件测试的两种不同的语法结构,它们有一些区别:

  1. \[\](方括号)是传统的条件测试结构,也被称为test命令。它是Shell的内置命令,用于进行条件判断。

    \[\]中的条件表达式可以使用标准的比较运算符(如-eq、-ne、-lt、-gt等)和逻辑运算符(如-a、-o、!等)。例如:

if $num -eq 5 ; then

​ echo "Number is equal to 5"

fi

  1. \[ ](双方括号)是Bash Shell的扩展语法,提供了更强大和灵活的条件测试功能。

    \[ ]结构支持更多的比较运算符(如==、!=、<、>等)和模式匹配(如*、?、...等)。

    它还支持逻辑运算符(如&&、||、!)和正则表达式匹配。例如:

if \[ $num == 5 ]; then

​ echo "Number is equal to 5"

fi

  1. \[ ]结构相对于\[\]结构还有其他一些优点,如更好的字符串处理能力、更灵活的变量扩展和更安全的文件名扩展。它还支持嵌套条件和更复杂的逻辑表达式。但需要注意的是,\[ ]结构只在Bash Shell中可用,不适用于其他Shell(如dash等)。

总的来说,\[\]是传统的条件测试结构,适用于基本的条件判断。而\[ ]是Bash Shell的扩展语法,提供了更强大和灵活的条件测试功能。如果你在Bash环境中,并且需要更复杂的条件判断和字符串处理,建议使用\[ ]结构

shell中 ,()和(())的区别是什么?

在Shell中,()和(())是两种不同的语法结构,它们有以下区别:

  1. ()(圆括号)用于创建子shell或命令组。当命令被放置在()中时,它们将在一个子shell中执行,这意味着其中的变量和环境将在子shell中创建和修改,不会影响到父shell。例如:

(command1; command2; command3)

  1. (())(双圆括号)用于执行算术运算和数值比较,而不是用于字符串比较,它支持整数运算、变量赋值和逻辑比较。在(())中,不需要使用$符号来引用变量。例如:

((x = 5 + 3))

或者

运算符前后需要有空格

x=9;

if ((x > 10)); then

​ echo "x is greater than 10"

fi

不建议使用(())进行字符串比较

x="hha"

if ((x == "hha")); then

echo "equal"

fi

尽管在正常情况下,(())结构主要用于数值运算和比较,但在某些Shell环境中,也可以用于字符串比较。

在Bash Shell中,(())结构可以进行字符串比较,但它会将字符串作为数值进行处理。当字符串可以被解释为有效的数值时,(())结构会将其转换为数值进行比较。如果字符串无法解释为有效的数值,则会产生错误。

在你的示例中,字符串x的值是"hha",它无法解释为有效的数值。然而,在某些Shell环境中,(())结构会将字符串作为0来处理,因此比较结果为真,进入了if语句块并输出"equal"。

尽管在某些Shell环境中可以使用(())结构进行字符串比较,但这种用法并不常见,容易引起混淆。为了更清晰和可读的代码,建议使用其他方式来进行字符串比较,如使用=或==运算符、test命令、\[ ]结构或case语句

(())结构还支持位运算、递增和递减操作等。

总的来说,()用于创建子shell或命令组,而(())用于执行算术运算和数值比较。它们在功能和用法上有明显的区别,因此需要根据具体的需求选择适合的语法结构

在(())中,不需要使用符号来引用变量,因为(())结构会自动识别和处理变量。如果你在(())中使用了符号来引用变量,也不会导致语法错误。

例如,下面是一个正确的(())示例:

if (( a == b ))

if (( a == b ))

等价

相关推荐
A小辣椒2 天前
TShark:Wireshark CLI 功能
linux
A小辣椒2 天前
TShark:基础知识
linux
AlfredZhao2 天前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao2 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334663 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪3 天前
linux 拷贝文件或目录到指定的位置
linux
摇滚侠3 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush43 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5203 天前
Linux 11 动态监控指令top
linux
不会C语言的男孩3 天前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言