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

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

  • 《Linux 系统命令及Shell脚本实践指南》
    • 该书从结构上分为三部分:
      • 第一部分
        • 1.1Linux的历史发展
        • 1.2用户管理
        • 1.3任务管理
          • 单一时刻执行一次任务使用at
          • 周期性任务使用:cron表达式,命令crontab
        • 1.4文件管理
          • 1.4.1 Linux shell 文件名中的通配符
        • 1.5 改变文件权限 chmod
        • 1.6网络管理
        • 1.7进程管理
        • 1.8 查看内存使用情况
        • 1.9 查看磁盘空间
      • 第二部分
        • vi 文件名 或者 vim 文件名
          • 查找模式
        • 基于流处理的sed,处理行
        • 基于流处理的awk,处理列
      • 第三部分
        • 定义变量、数组
        • 测试结构 test 或者 [ ]
          • 逻辑测试
          • 字符串测试
            • 字符串的比较
          • 数值测试【可以使用[ ]、[[ ]]、(( ))】
          • 文件测试
        • if/elif/else
        • case...esac
        • for/while
        • 函数
      • 其它
        • 多行输入
        • shell中的计算
        • shell中 ,[] 和[[ ]]的区别是什么?
        • 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. 方括号([]):匹配方括号中列出的任意一个字符。例如,file[123].txt可以匹配file1.txt、file2.txt或file3.txt。

  4. 范围(-):在方括号中使用范围来匹配一定范围内的字符。例如,file[a-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 主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等。

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

基于流处理的awk,处理列

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

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

# 每行按空格或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等循环语句,最后加上函数和输入输出重定向。

定义变量、数组

#!/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语法中,应该使用=运算符来进行字符串比较。以下是使用=运算符进行字符串相等判断的示例:

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
#判断两个字符串是否相等
#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

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

casein
模式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

# 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


函数

# 定义函数
 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脚本中的命令和语句都可以通过换行符进行分隔,而不需要使用分号。分号主要用于在同一行上写多个命令或语句

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

   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 ))

等价

你可能感兴趣的:(linux,shell)