Linux——Shell的基本编程规范与变量

发布于:2025-04-11 ⋅ 阅读:(33) ⋅ 点赞:(0)

目录

引言

Shell的作用

总结

Shell脚本的基本编程

1、脚本种类

2、编写第一个Shell脚本 

 重定向与管道操作

1:重定向

使用shell变量

1:自定义变量

2:查看和引用变量的值

3:变量赋值的特殊操作

4:设置变量的作用范围

5:数值变量的运算

特殊的shell变量

1:环境变量

2:位置变量

3:预定义变量

重定向与管道操作

1:重定向

Shell脚本与计划任务

1:确定备份方案

3:设置计划任务


引言

    没想到吧,我其实一直都在!(没错,我在进行试验。)一刻没有为“清明假期”的结束而感到悲伤,紧接着向我们走来的是“劳动节假期”!

    为什么之前的帖子质量较于之前很低呢?其实我也清楚大家对于这些并不在意,那就这样吧。总的来说,AI生成的文案会被限流。即使质量对于其他人要高许多,也大概率无法上榜的(仅个人而言)。

    那么也不多说了,毕竟那些人对于这些感兴趣呢?我大可不写,甚至连相关知识都不用查。但我清楚的明白我写这些对于我的作用与意义。谁爱看谁看吧...榜?给我钱吗,我那么卖命。我对得起我自己就行了,毕竟学IT的人本来就少,喜欢评论的人更是凤毛麟角,我还能祈求什么呢?

Shell的作用

    早在以往的帖子中,我们就已经初步了解它的主要作用,但那时也只是对于“它与内核之间命令的主要区别”进行讲解。(如果忘记就自行去查找吧)然而今天,Shell就是今天与往后一段时间的主角。

    Shell 是 Linux 操作系统的核心组件之一,它是用户与系统内核(Kernel)之间的“中间人”,负责解释和执行用户的命令,同时提供丰富的功能来管理系统、自动化任务和定制工作环境。以下是 Shell 的主要作用:

1. ‌用户与内核的交互接口

  • 核心功能‌:Shell 是用户与 Linux 内核之间的“翻译器”。用户通过 Shell 输入文本命令(如 lsmkdir),Shell 将这些命令解析后传递给内核执行,并将结果返回给用户。
  • 示例‌:当输入 ls -l 时,Shell 会调用内核的文件系统接口,列出当前目录的详细信息。
  • 意义‌:用户无需直接操作复杂的系统调用(System Call),通过 Shell 即可完成大部分任务。

2. ‌脚本自动化(Shell Scripting)

  • 核心功能‌:Shell 允许用户将一系列命令写入脚本文件(如 backup.sh),实现自动化操作(如批量处理文件、定时任务等)。
  • 示例‌:编写脚本自动备份日志、部署服务或监控系统资源。
  • 意义‌:显著提高重复性任务的效率,减少人工干预。

3. ‌系统管理与配置

  • 核心功能‌:Shell 是系统管理员的核心工具,用于管理用户、权限、软件包、网络、进程等。
  • 常见操作‌:
    • 用户管理:useraddpasswd
    • 权限管理:chmodchown
    • 软件安装:apt-getyum
    • 进程控制:pskillsystemctl
  • 意义‌:几乎所有系统级别的操作都可以通过 Shell 完成。

4. ‌灵活的组合与扩展(管道与重定向)

  • 核心功能‌:Shell 支持命令的组合(管道 |)和输入输出重定向(><>>),允许用户将多个命令串联使用。
  • 示例‌:
    • cat file.txt | grep "error" > errors.log:提取文件中的错误信息并保存到日志。
    • curl -s http://example.com | wc -l:统计网页内容的行数。
  • 意义‌:通过简单命令的组合实现复杂功能。

5. ‌环境定制与开发支持

  • 核心功能‌:用户可以通过 Shell 配置文件(如 ~/.bashrc~/.zshrc)定制自己的工作环境。
  • 常见定制‌:
    • 别名(Alias):alias ll='ls -l' 简化常用命令。
    • 环境变量:设置 PATHJAVA_HOME 等变量。
    • 提示符(Prompt):自定义终端外观。
  • 意义‌:提升个人或团队的工作效率。

总结

Shell 在 Linux 中的核心价值‌:

  1. 桥梁作用‌:作为用户与内核的纽带,简化了系统操作。
  2. 自动化引擎‌:通过脚本将重复性工作流程化,提升效率。
  3. 系统管理中枢‌:几乎所有的系统配置、监控和维护都依赖 Shell。
  4. 开发与运维工具链‌:支持开发调试、环境配置和故障排查。
  5. 高度可定制性‌:允许用户打造个性化的高效工作环境。

    但这些相较于今天的主要内容... ...都不重要!因为今天主要讲的是——Shell脚本的基本编程其变量的作用及类型

Shell脚本的基本编程

1、脚本种类

[root@localhost ~]#cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin    ......//省略内容

2、编写第一个Shell脚本 

[root@localhost ~]# vi first.sh
cd /boot/
pwd
ls -lh vml*
[root@localhost ~]# chmod +x first.sh
[root@localhost ~]# ./first.sh
[root@localhost ~]# vi first.sh
#!/bin/bash
#this is my first shell script
cd /boot/
echo "当前的目录位于:"
pwd
echo "其中以vml开头的文件包括:"
ls -lh vml*
[root@localhost ~]# ./first.sh
[root@localhost ~]# sh first.sh
[root@localhost ~]# bash first.sh
[root@localhost ~]# . first.sh
[root@localhost ~]# source first.sh

    注释:“./”、sh、bash是相同的执行方式,“.”和source是相同的;

    source和“.”执行脚本时,将脚本中语句在本shell中执行,

    sh、bash和./是在执行脚本时先启动一个新的shell,然后让脚本中的语句在新的shell中执行,执行完后就退出。

 重定向与管道操作

1:重定向
1):重定向输出
[root@localhost ~]# uname -p > kernel.txt
[root@localhost ~]# cat kernel.txt
[root@localhost ~]# uname -r >> kernel.txt       \\追加并保存,不覆盖原有的数据
[root@localhost ~]# cat kernel.txt
扩展:

[root@localhost ~]# sed -i '1a\aaa' 123.txt   #在第一行的下一行添加文字
[root@localhost ~]# sed -i '1i\aaa' 123.txt    #在第一行的上一行添加文字
2):重定向输入

[root@localhost ~]# echo "123456">pass.txt
[root@localhost ~]# useradd aaa
[root@localhost ~]# passwd --stdin aaa <pass.txt       \\selinux要设置为disabled
或
[root@localhost ~]# echo aptech | passwd --stdin aaa    \\不用关闭selinux
3):重定向错误

[root@localhost ~]# tar jcf /nonedir/etc.tgz /etc/ 2>error.log
[root@localhost ~]# cat error.log
案例:

[root@localhost ~]# vi httpd_install.sh

#!/bin/bash
# 自动编译安装httpd服务器脚本
tar zxvf httpd-2.4.25.tar.gz &>/dev/null

cd httpd-2.4.25

yum -y install gcc apr-devel apr-util apr-util-devel pcre-devel

./configure --prefix=/usr/local/httpd --enable-so &>/dev/null

make &>/dev/null

make install &> /dev/null

echo "正在安装,请稍后......"

echo "http test">/usr/local/httpd/htdocs/index.html

/usr/local/httpd/bin/apachectl start >/dev/null

curl 127.0.0.1 
[root@localhost ~]# chmod +x httpd_install.sh
[root@localhost ~]# ./httpd_install.sh

2:管道操作

[root@localhost ~]# grep "/bin/bash$" /etc/passwd           \\以bash结尾的行
[root@localhost ~]# grep "/bin/bash$" /etc/passwd | awk -F: '{print $1,$7}'
[root@localhost ~]# df -hT
[root@localhost ~]# df -hT | grep "/$" | awk '{print $6}'    #根目录下磁盘利用率

使用shell变量

变量名不能用数字开头

变量名中不能有小数点

变量名不能用纯数字

变量名可以是字母开头再加数字,或下划线开头加字母或数字

变量名中不能有斜杠“/”、“$”、“#”、“@”等特殊符号

等号前后不能加空格

1:自定义变量

[root@localhost ~]# name=benet

[root@localhost ~]# version=5.0

2:查看和引用变量的值

[root@localhost ~]# echo $name
benet
[root@localhost ~]# echo $name$version
benet 5.0
[root@localhost ~]# echo $name4.5           \\错误的引用
.5
[root@localhost ~]# echo ${name}4.5
benet4.5

注意:引用变量时如果变量名后有其他的字符,要将变量名应大括号引起来,用以定界

3:变量赋值的特殊操作

1):双引号

双引号可用于字符串的声明,双引号中的$符号或当做变量进行输出。连续的字符可以省略双引号,字符串中有空格的话就不能省略,另外,声明的变量值中如果要引用另一个变量,也需要双引号。

[root@localhost ~]# name=benet 5.0        \\错误的赋值
bash: 5.0: command not found
[root@localhost ~]# namet="benet 5.0"
[root@localhost ~]# echo $name
[root@localhost ~]# accp="accp $version"
[root@localhost ~]# echo $accp
accp 5.0
2):单引号

单引号用于原样输出的变量声明,意思是变量的值中需要保留显示$符号
[root@localhost ~]# accp='accp $version'
[root@localhost ~]# echo $accp
accp $version                     \\单引号中不能再引用变量,因此此处是错误的输出
3):反撇号

反引号用于命令的引用,相当于$(),区别在于反引号不能嵌套,而$()可以嵌套

[root@localhost ~]# ls -lh `which useradd`
[root@localhost ~]# aaa=`grep -v "^#" /etc/profile`
[root@localhost ~]# echo $aaa
[root@localhost ~]# rpm -qc $(rpm -qf $(which useradd))
备注:

-qf:查找该文件属于哪一个已安装的软件包

-qc:列出该软件包生成的所有文件
4):read命令

[root@localhost ~]# read todir1
/opt/backup/                \\用户输进去的
[root@localhost ~]# echo $todir1
/opt/backup/
[root@localhost ~]# read -p "请制定备份存放的目录:" todir2
请制定备份存放的目录:/opt/backup
[root@localhost ~]# echo $todir2
/opt/backup

综合案例

[root@localhost ~]# vi httpd_install.sh

#!/bin/bash

# 自动编译安装httpd服务器脚本 

read -p 请输入源码包的目录: mydir

cd $mydir

read -p 请输入软件包的名字: pack

tar zxvf ${pack}*.tar.gz &>/dev/null

cd /$mydir/${pack}* 

./configure --prefix=/usr/local/$pack &>/dev/null

make &>/dev/null

make install &> /dev/null

/usr/local/httpd/bin/apachectl start

firefox 127.0.0.1

[root@localhost ~]# chmod +x httpd_install.sh
[root@localhost ~]# ./httpd_install.sh 
4:设置变量的作用范围
1):例1

[root@localhost ~]# echo "name $version"
product 5.0
[root@localhost ~]# bash
[root@localhost ~]# echo "name$version"
product
[root@localhost ~]# exit
exit
[root@localhost ~]# echo "name$version"
product 5.0
2):例2

[root@localhost ~]# echo "name$version"
name5.0
[root@localhost ~]# echo "$name$version"
benet 5.0
[root@localhost ~]# export name version \\导出为全局变量
[root@localhost ~]# bash
[root@localhost ~]# echo "$name$version"
benet 5.0
[root@localhost ~]# exit
exit
3):例3

[root@localhost ~]# export fqdn="www.benet.com"
[root@localhost ~]# echo $fqdn

5:数值变量的运算
[root@localhost ~]# x=35
[root@localhost ~]# y=16
[root@localhost ~]# expr $x+$y
35+16
[root@localhost ~]# expr $x + $y
51
[root@localhost ~]# expr $x - $y
19
[root@localhost ~]# expr $x \* $y
560
[root@localhost ~]# expr $x / $y
2
[root@localhost ~]# expr $x % $y
3
[root@localhost ~]# Ycube=`expr $y \* $y \* $y`
[root@localhost ~]# echo $Ycube
4096
[root@localhost ~]# a=2
[root@localhost ~]# echo $((a*3))
6
[root@localhost ~]# echo $((a**3))   #3次方
8

特殊的shell变量

1:环境变量

    set命令也可以显示环境变量,它显示的是系统中所有的环境变量,包括全局变量和局部变量

env只显示全局变量。示例如下:


[root@localhost ~]# env
[root@localhost ~]# ls -lh /root/first.sh
[root@localhost ~]# echo $PATH
[root@localhost ~]# first.sh
bash: first.sh: command not found

[root@localhost ~]# PATH="$PATH:/root"
[root@localhost ~]# echo $PATH
[root@localhost ~]# first.sh
/boot
[root@localhost ~]# vi /etc/profile
修改
export HISTORYSIZE=20
[root@localhost ~]# history | wc -l
89
[root@localhost ~]# source /etc/profile
[root@localhost ~]# history | wc -l
20
2:位置变量
[root@localhost ~]# vi adder2num.sh
#!/bin/bash

SUM=`expr $1 + $2`

echo "$1 + $2 = $SUM"

[root@localhost ~]# chmod +x adder2num.sh
[root@localhost ~]# ./adder2num.sh 12 14
12 + 14 = 26
3:预定义变量

$# 传送给命令Shell的参数个数

$- 在Shell启动或使用set命令时提供选项

$? 上一条命令执行后返回的值

$$ 当前shell的进程号

$! 上一个子进程的进程号

$@ 所有的参数,每个都用双括号括起

$* 所有参数,用双括号括起

$n 位置参数值,n表示位置

$0 当前shell名

备注:

$@:输出所有参数,把输出的参数当做一个个独立的单词,便于遍历所有的参数

$*:输出所有参数,把所有输出的参数当做一个整体。

这两个变量在输出时,视觉上是一样的,但存储方式不一样

(1)例1

[root@localhost ~]# vi mybak.sh

#!/bin/bash

TARFILE=beifen-`date +%s`.tgz

tar zcf $TARFILE $* &> /dev/null

echo "已执行 $0 脚本,"

echo "共完成 $# 个对象的备份"

echo “具体内容包括: $*”

[root@localhost ~]# chmod +x mybak.sh
[root@localhost ~]# ./mybak.sh /boot/grub
已执行 ./mybak.sh 脚本,
共完成 1 个对象的备份
“具体内容包括: /boot/grub”

[root@localhost ~]# ./mybak.sh /etc/passwd /etc/shadow
已执行 ./mybak.sh 脚本,
共完成 2 个对象的备份
“具体内容包括: /etc/passwd /etc/shadow”

[root@localhost ~]# ls -lh beifen-*
-rw-r--r--. 1 root root 101K 12月  1 22:36 beifen-1448980601.tgz
-rw-r--r--. 1 root root 1.1K 12月  1 22:37 beifen-1448980640.tgz

(2)例2

[root@localhost ~]# vi adder2num.sh

#!/bin/bash

SUM=`expr $1 + $2`

echo "$1 + $2 = $SUM"

echo $0

echo $#

echo $*

echo $@

重定向与管道操作

1:重定向
1):重定向输出
[root@localhost ~]# uname -p > kernel.txt
[root@localhost ~]# cat kernel.txt
[root@localhost ~]# uname -r >> kernel.txt       \\追加并保存,不覆盖原有的数据
[root@localhost ~]# cat kernel.txt
扩展:

[root@localhost ~]# sed -i '1a\aaa' 123.txt   #在第一行的下一行添加文字
[root@localhost ~]# sed -i '1i\aaa' 123.txt    #在第一行的上一行添加文字
2):重定向输入

[root@localhost ~]# echo "123456">pass.txt
[root@localhost ~]# useradd aaa
[root@localhost ~]# passwd --stdin aaa <pass.txt       \\selinux要设置为disabled
或
[root@localhost ~]# echo aptech | passwd --stdin aaa    \\不用关闭selinux
3):重定向错误

[root@localhost ~]# tar jcf /nonedir/etc.tgz /etc/ 2>error.log
[root@localhost ~]# cat error.log
案例:

[root@localhost ~]# vi httpd_install.sh

#!/bin/bash
# 自动编译安装httpd服务器脚本
tar zxvf httpd-2.4.25.tar.gz &>/dev/null

cd httpd-2.4.25

yum -y install gcc apr-devel apr-util apr-util-devel pcre-devel

./configure --prefix=/usr/local/httpd --enable-so &>/dev/null

make &>/dev/null

make install &> /dev/null

echo "正在安装,请稍后......"

echo "http test">/usr/local/httpd/htdocs/index.html

/usr/local/httpd/bin/apachectl start >/dev/null

curl 127.0.0.1 
[root@localhost ~]# chmod +x httpd_install.sh
[root@localhost ~]# ./httpd_install.sh

2:管道操作

[root@localhost ~]# grep "/bin/bash$" /etc/passwd           \\以bash结尾的行
[root@localhost ~]# grep "/bin/bash$" /etc/passwd | awk -F: '{print $1,$7}'
[root@localhost ~]# df -hT
[root@localhost ~]# df -hT | grep "/$" | awk '{print $6}'    #根目录下磁盘利用率

Shell脚本与计划任务

1:确定备份方案
mysql> grant select,lock tables on mysql.* to 'root'@'192.168.4.110' identified by 'pwd123';

mysql> grant select,lock tables on test.* to 'root'@'192.168.4.110' identified by 'pwd123';

[root@localhost mysql-5.5.22]# mysqldump -u root -p -h localhost --databases test > test.sql
[root@localhost mysql-5.5.22]# mysqldump -u root -p -h localhost --databases mysql > mysql.sql
[root@localhost mysql-5.5.22]# ls -lh test.sql
-rw-r--r--. 1 root root 0 12月  1 22:46 test.sql

2:编写mysql备份脚本

[root@localhost mysql-5.5.22]# mysqladmin -u root -p password 'aptech'
[root@localhost mysql-5.5.22]# mkdir -p /opt/qnzx_dbbak/
[root@localhost mysql-5.5.22]# vi qnzx_dbbak.sh

#!/bin/bash
# 这是一个MySQL数据库逻辑备份脚本
# 1.定义数据库的连接、目标库信息

MY_USER="root"

MY_PASS="aptech"

MY_HOST="localhost"

MY_CONN="-u $MY_USER -p$MY_PASS -h $MY_HOST"

MY_DB1="mysql"

MY_DB2="test"

# 2.定义备份目录、工具、时间、文件名主体

BF_DIR="/opt/qnzx_dbbak"

BF_CMD="/usr/local/mysql/bin/mysqldump"

BF_TIME=`date +%Y%m%d-%H%M`

NAME_1="$MY_DB1-$BF_TIME"

NAME_2="$MY_DB2-$BF_TIME"

# 3.先导出为.sql脚本,然后再进行压缩(打包后删除原文件)
cd $BF_DIR

$BF_CMD $MY_CONN --databases $MY_DB1 > $NAME_1.sql

$BF_CMD $MY_CONN --databases $MY_DB2 > $NAME_2.sql

/bin/tar zcf $NAME_1.tar.gz $NAME_1.sql --remove &> /dev/null

/bin/tar zcf $NAME_2.tar.gz $NAME_2.sql --remove &> /dev/null

[root@localhost mysql-5.5.22]# chmod +x qnzx_dbbak.sh
[root@localhost mysql-5.5.22]# vi qnzx_dbbak.sh
[root@localhost mysql-5.5.22]# ./qnzx_dbbak.sh
[root@localhost mysql-5.5.22]# ls -lh /opt/qnzx_dbbak/*.gz
3:设置计划任务
[root@localhost mysql-5.5.22]# mv qnzx_dbbak.sh /opt/qnzx_dbbak/
[root@localhost mysql-5.5.22]# crontab -e
添加
30 2 * * * /opt/qnzx_dbbak/qnzx_dbbak.sh

[root@localhost mysql-5.5.22]# service crond status