当前位置:首页 > 经验 >

shsh怎么使用(shsh要在哪里下载)

来源:原点资讯(www.yd166.com)时间:2022-10-29 15:07:22作者:YD166手机阅读>>

shell 原意是“外壳”,与 kernel(内核)相对应,比喻内核外的一层,是用户和内核沟通的桥梁。shell 有很多种,国内通常使用 bash。

第一个 shell 脚本

创建 hello-world.sh 文件,内容如下:

test11@pjl:~/tmp$ vim hello-world.sh

#!/bin/bash echo 'hello world'

第一行指定 SHELL 的类型:

test11@pjl:~/tmp$ echo $SHELL /bin/bash

Tip:通常约定以 sh 结尾。提前剧透:

test11@pjl:~/tmp$ sh hello-world.xx hello world

执行 sh 文件,提示权限不够:

test11@pjl:~/tmp$ ./hello-world.sh -bash: ./hello-world.sh: 权限不够

test11@pjl:~/tmp$ ll -rw-rw-r-- 1 test11 test11 31 6月 17 16:18 hello-world.sh

增加可执行权限:

test11@pjl:~/tmp$ chmod u x hello-world.sh test11@pjl:~/tmp$ ll # hello-world.sh 变绿了 -rwxrw-r-- 1 test11 test11 31 6月 17 16:18 hello-world.sh*

使用相对路径方式再次执行即可:

test11@pjl:~/tmp$ ./hello-world.sh hello world

也可以使用绝对路径执行:

test11@pjl:~/tmp$ /home/test11/tmp/hello-world.sh hello world

通过 sh xx.sh 无需可执行权限也可以执行。

Tip:下文还会使用 bash xx.sh 的执行方式。

首先删除可执行权限:

test11@pjl:~/tmp$ chmod u-x hello-world.sh test11@pjl:~/tmp$ ll 总用量 20 -rw-rw-r-- 1 test11 test11 31 6月 17 16:18 hello-world.sh

test11@pjl:~/tmp$ sh hello-world.sh hello world shell 注释

  • 单行注释:# 内容
  • 多行注释:

:<<! 内容1 内容2 ... 内容N ! 变量系统变量

例如 $SHELL 就是系统变量:

test11@pjl:~/tmp$ echo $SHELL /bin/bash

可以通过 set 查看系统变量。例如过滤 SHELL 系统变量:

test11@pjl:~/tmp$ set |more |grep SHELL SHELL=/bin/bash SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor 自定义变量

定义变量age并输出:

test11@pjl:~/tmp$ vim demo.sh test11@pjl:~/tmp$ sh demo.sh age=18 age=18

内容如下:

test11@pjl:~/tmp$ cat demo.sh #!/bin/bash age=18 echo age=$age echo "age=$age"

:1. 定义变量不要在等号前后加空格;2. 使用变量要使用 $;3. 最后两行输出效果相同

# `age=18` 改为 `age= 18` test11@pjl:~/tmp$ sh demo.sh demo.sh: 2: 18: not found age= age=

使用 unset 可以销毁变量。请看示例:

test11@pjl:~/tmp$ vim demo.sh test11@pjl:~/tmp$ sh demo.sh age=18 age= # 脚本内容 test11@pjl:~/tmp$ cat demo.sh #!/bin/bash age=18 echo age=$age unset age echo age=$age

:销毁变量 age 后再使用该变量,没有报错。

通过 readonly 定义静态变量,不能 unset。请看示例:

test11@pjl:~/tmp$ vim demo.sh test11@pjl:~/tmp$ sh demo.sh age=18 demo.sh: 4: unset: age: is read only test11@pjl:~/tmp$ cat demo.sh #!/bin/bash readonly age=18 echo age=$age unset age

变量定义规则:

  • 字母数字下划线,不能以数字开头
  • 等号两侧不能有空格
  • 变量名习惯大写

可以将命令运行结果赋予变量。请看示例:

命令 date:

test11@pjl:~/tmp$ date 2022年 06月 17日 星期五 16:52:57 CST

test11@pjl:~/tmp$ vim demo.sh test11@pjl:~/tmp$ sh demo.sh date1=2022年 06月 17日 星期五 16:54:02 CST date2=2022年 06月 17日 星期五 16:54:02 CST

test11@pjl:~/tmp$ cat demo.sh #!/bin/bash date1=`date` date2=$(date) echo date1=$date1 echo date2=$date2 环境变量

比如我在多个 .sh 文件中需要使用一个公共的变量,这时就可以使用环境变量,或称之为全局变量。

环境变量通过 export=value 定义在 /etc/profile 文件中。请看第 30 行:

test11@pjl:~$ cat -n /etc/profile 1 # /etc/profile: system-wide .profile file for the Bourne shell (sh(1)) 2 # and Bourne compatible shells (bash(1), ksh(1), ash(1), ...). 3 4 if [ "${PS1-}" ]; then 5 if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then 6 # The file bash.bashrc already sets the default PS1. 7 # PS1='\h:\w\$ ' 8 if [ -f /etc/bash.bashrc ]; then 9 . /etc/bash.bashrc 10 fi 11 else 12 if [ "`id -u`" -eq 0 ]; then 13 PS1='# ' 14 else 15 PS1='$ ' 16 fi 17 fi 18 fi 19 20 if [ -d /etc/profile.d ]; then 21 for i in /etc/profile.d/*.sh; do 22 if [ -r $i ]; then 23 . $i 24 fi 25 done 26 unset i 27 fi 28 29 30 export ANDROID_HOME=/home/pjl/software/android-studio-2021.1.1.22-linux/android-studio/bin 31 export PATH=$PATH:$ANDROID_HOME

这里定义了一个环境变量 ANDROID_HOME,将其输出看一下:

test11@pjl:~$ echo $ANDROID_HOME /home/pjl/software/android-studio-2021.1.1.22-linux/android-studio/bin

现在我们定义一个环境变量 EVN-VAR-TEST=pjl:

# 查看文件最后两行 root@pjl:/home/test11# tail -2 /etc/profile export PATH=$PATH:$ANDROID_HOME export EVN_VAR_TEST=pjl

新的环境变量需要执行 source 才能立即生效。请看实例:

# 新的环境变量未生效 root@pjl:/home/test11# echo $EVN_VAR_TEST # 修改后的配置信息立即生效 root@pjl:/home/test11# source /etc/profile # 新的环境变量已生效 root@pjl:/home/test11# echo $EVN_VAR_TEST pjl

尝试在 demo.sh 中使用新增环境变量。请看示例:

test11@pjl:~/tmp$ cat demo.sh #!/bin/bash :<<! date1=`date` date2=$(date) echo date1=$date1 echo date2=$date2 ! echo env_var_test=$EVN_VAR_TEST

运行 demo.sh,发现变量为空,让配置立即生效即可:

test11@pjl:~/tmp$ sh demo.sh env_var_test= test11@pjl:~/tmp$ echo $EVN_VAR_TEST test11@pjl:~/tmp$ source /etc/profile

test11@pjl:~/tmp$ echo $EVN_VAR_TEST pjl test11@pjl:~/tmp$ sh demo.sh env_var_test=pjl

:笔者以 root 用户新增环境变量,并让配置生效,接着切换到 test11 用户,需要再次让配置生效。

位置参数变量

请先看示例:

test11@pjl:~/tmp$ sh demo.sh 100 200 demo.sh 100 200 100 200 100 200 2

test11@pjl:~/tmp$ cat demo.sh #!/bin/bash echo $0 $1 $2 echo $* echo $@ echo $#

语法介绍:

  • $0 - 命令本身
  • $1 - 第一个参数。第10个参数需要写成 ${10}
  • $* - 命令行中所有参数。所有参数看做一个整体
  • $@ - 命令行中所有参数。把每个参数区分对待
  • $# - 参数个数
预定义变量

shell设计者预先定义变量,可以在 shell 脚本中直接使用。

Tip:用得不多,仅做了解

语法介绍:
$$ - 当前进程的进程号
$! - 后台运行的最后一个进程的进程号
$? - 最后一次执行的命名的返回状态。0 表示执行成功。

请看示例:

test11@pjl:~/tmp$ sh demo.sh 29174 test11@pjl:~/tmp$ cat demo.sh #!/bin/bash echo $$ 运算符

请看示例:

test11@pjl:~/tmp$ ./demo.sh 1 8 v1=18 v2=18 v3=18 v4=9

test11@pjl:~/tmp$ cat -n demo.sh 1 #!/bin/bash 2 v1=$(((1 8)*2)) 3 echo v1=$v1 4 # 推荐 5 v2=$[(1 8)*2] 6 echo v2=$v2 7 8 tmp=`expr 1 8` 9 v3=`expr $tmp \* 2` 10 echo v3=$v3 11 12 v4=$[$1 $2] 13 echo v4=$v4

语法介绍:

  • 有三种运算的方式:$((运算符))、$[运算式]、expr a b。推荐使用 $[]
  • expr 运算符需要有空格,例如 expr 1 8 就没有空格,而且乘号需要加一个转义符 \*
Syntax error: "(" unexpected

test11@pjl:~/tmp$ sh demo2.sh demo2.sh: 2: Syntax error: "(" unexpected test11@pjl:~/tmp$ cat -n demo2.sh 1 #!/bin/bash 2 v1=$[(1 8)*2] 3 echo v1=$v1

据网友介绍:ubuntu 上 sh 命令默认是指向 dash,而不是 bash。dash 比 bash 更轻量,只支持基本的 shell 功能,有些语法不识别。可以直接用 bash a.sh,或者./a.sh 来执行脚本。

改为 bash 或 ./ 的方式执行,确实可以。请看示例:

test11@pjl:~/tmp$ bash demo2.sh v1=18 if

语法有点怪,先看示例:

test11@pjl:~/tmp$ sh demo2.sh abc 等于 abc 100 大于等于 99 存在 /home/test11/tmp/demo2.sh

test11@pjl:~/tmp$ cat -n demo2.sh 1 #!/bin/bash 2 if [ 'abc'='abc' ] 3 then 4 echo 'abc 等于 abc' 5 fi 6 7 if [ 100 -ge 99 ] 8 then 9 echo '100 大于等于 99' 10 fi 11 12 if [ -f /home/test11/tmp/demo2.sh ] 13 then 14 echo '存在 /home/test11/tmp/demo2.sh' 15 fi

语法介绍:

  • if 判断使用 [ 条件 ] 语法,[] 前后要有空格
  • 字符串比较用 =。非空返回 true
  • 数字比较:-lt 小于、-le 小于等于、-eq 等于、-gt 大于、-ge 大于等于、-ne 不等于
  • 文件权限进行判断:-r 有读的权限、-w 有写的权限、-e 有执行的权限
  • 文件类型进行判断:-f 文件存在且是一个常规文件、-e 文件存在、-d 文件存在并是一个目录

:[] 前后要有空格,否则会报错。请看示例:

test11@pjl:~/tmp$ sh demo2.sh demo2.sh: 2: []: not found test11@pjl:~/tmp$ cat demo2.sh #!/bin/bash if [] then echo '空字符' fi

增加一个空格,由于空字符是假值,所以不会有输出:

test11@pjl:~/tmp$ sh demo2.sh test11@pjl:~/tmp$ cat demo2.sh #!/bin/bash if [ ] then echo '空字符' fi elseif

请看示例:

test11@pjl:~/tmp$ sh demo2.sh dog 狗,100块 test11@pjl:~/tmp$ sh demo2.sh cat 猫,102块

test11@pjl:~/tmp$ cat demo2.sh #!/bin/bash # echo 参数1=$1 if [ $1 = "dog" ] then echo '狗,100块' elif [ $1 = "cat" ] then echo '猫,102块' fi

类似前端的 if...elseif...elseif。

case

请看示例,如果传参是 dog ,输出 '狗':

test11@pjl:~/tmp$ sh demo2.sh dog 狗 test11@pjl:~/tmp$ sh demo2.sh cat 猫 test11@pjl:~/tmp$ sh demo2.sh xx 其他动物 test11@pjl:~/tmp$ cat demo2.sh #!/bin/bash case $1 in "dog") echo '狗' ;; "cat") echo '猫' ;; *) echo '其他动物' ;; esac

语法介绍:

case $变量名 in "值1") 变量的值等于“值1”,执行程序1 ;; "值2") 变量的值等于“值2”,执行程序2 ;; *) 都不满足,执行 ;; esac 循环for

// 具体的几个值 for i in v1 v2 v3 ... do 程序 done

以下示例演示了 $@ 和 $* 的区别:

test11@pjl:~/tmp$ sh demo2.sh a b c num1=a num1=b num1=c num2=a b c

test11@pjl:~/tmp$ cat demo2.sh #!/bin/bash for i in "$@" do echo num1=$i done for i in "$*" do echo num2=$i done

你有几个参数,$@ 就把你当做几个;$* 只会把你当做一个整体;

语法二

for (( 初始值;循环控制条件;变量变化)) do 程序 done

请看示例:

test11@pjl:~/tmp$ bash demo2.sh 100 1 到 100 的和:5050

test11@pjl:~/tmp$ cat -n demo2.sh 1 #!/bin/bash 2 3 sum=0 4 for(( i=1; i <= $1; i )) 5 do 6 sum=$[$sum $i] 7 done 8 echo 1 到 $1 的和:$sum

:第6行不要写成 $sum=$[$sum $i]

while

请看示例:

test11@pjl:~/tmp$ bash demo2.sh 100 1 到 100 的和:5050

test11@pjl:~/tmp$ cat -n demo2.sh 1 #!/bin/bash 2 3 sum=0 4 i=1 5 6 # while [ $i <= $1 ] 7 while [ $i -le $1 ] 8 do 9 sum=$[$sum $i] 10 i=$[$i 1] 11 done 12 13 echo 1 到 $1 的和:$sum

假如把第 6 行放开,报错如下:

test11@pjl:~/tmp$ bash demo2.sh 100 demo2.sh: 行 6: =: 没有那个文件或目录 1 到 100 的和:0

语法介绍:

while [ 条件判断 ] do 程序 done

Tip:while 和 [ 之间有空格;条件判断与 ] 有空格。例如删除一个空格就会报错 while[ $i -le $1 ]:

test11@pjl:~/tmp$ bash demo2.sh 100 demo2.sh: 行 6: while[ 1 -le 100 ]:未找到命令 demo2.sh: 行 7: 未预期的符号“do”附近有语法错误 demo2.sh: 行 7: `do' read 获取控制台输入

test11@pjl:~/tmp$ sh demo2.sh 请输入你个名字:

程序会阻塞,当你输入后会继续执行:

test11@pjl:~/tmp$ sh demo2.sh 请输入你个名字:pjl name=pjl

通过 -t 参数能指定等待时间(秒),例如 5 秒内如果没有输入,程序会继续执行:

test11@pjl:~/tmp$ bash demo2.sh 请输入你个名字:name= test11@pjl:~/tmp$ cat demo2.sh #!/bin/bash read -t 5 -p 请输入你个名字: name

语法:read 选项 参数。

test11@pjl:~/tmp$ read -h -bash: read: -h:无效选项 read:用法: read [-ers] [-a 数组] [-d 分隔符] [-i 缓冲区文字] [-n 读取字符数] [-N 读取字符数] [-p 提示符] [-t 超时] [-u 文件描述符] [名称 ...] test11@pjl:~/tmp$ read --help read: read [-ers] [-a 数组] [-d 分隔符] [-i 缓冲区文字] [-n 读取字符数] [-N 读取字符数] [-p 提示符] [-t 超时] [-u 文件描述符] [名称 ...] 从标准输入读取一行并将其分为不同的域。 从标准输入读取单独的一行,或者如果使用了 -u 选项,从文件描述符 FD 中读取。 该行被分割成域,如同词语分割一样,并且第一个词被赋值给第一个 NAME 变量,第二 个词被赋值给第二个 NAME 变量,如此继续,直到剩下所有的词被赋值给最后一个 NAME 变量。只有 $IFS 变量中的字符被认作是词语分隔符。 如果没有提供 NAME 变量,则读取的行被存放在 REPLY 变量中。 选项: -a array 将词语赋值给 ARRAY 数组变量的序列下标成员,从零开始 -d delim 持续读取直到读入 DELIM 变量中的第一个字符,而不是换行符 -e 使用 Readline 获取行 -i text 使用 TEXT 文本作为 Readline 的初始文字 -n nchars 读取 nchars 个字符之后返回,而不是等到读取换行符。 但是分隔符仍然有效,如果遇到分隔符之前读取了不足 nchars 个字符。 -N nchars 在准确读取了 nchars 个字符之后返回,除非遇到文件结束符或者读超时, 任何的分隔符都被忽略 -p prompt 在尝试读取之前输出 PROMPT 提示符并且不带 换行符 -r 不允许反斜杠转义任何字符 -s 不回显终端的任何输入 -t timeout 如果在 TIMEOUT 秒内没有读取一个完整的行则超时并且返回失败。 TMOUT 变量的值是默认的超时时间。TIMEOUT 可以是小数。 如果 TIMEOUT 是 0,那么仅当在指定的文件描述符上输入有效的时候, read 才返回成功;否则它将立刻返回而不尝试读取任何数据。 如果超过了超时时间,则返回状态码大于 128 -u fd 从文件描述符 FD 中读取,而不是标准输入 退出状态: 返回码为零,除非遇到了文件结束符、读超时(且返回码不大于128)、 出现了变量赋值错误或者无效的文件描述符作为参数传递给了 -u 选项。 函数

请看示例:

test11@pjl:~/tmp$ bash demo2.sh sum=300

test11@pjl:~/tmp$ cat demo2.sh #!/bin/bash # 定义函数 function sum() { # 第一个参数为 $1 sum=$[$1 $2] echo sum=$sum } # 执行函数 sum 100 200

语法介绍:

[ function ] funname [()] { action; [return int;] } 系统函数

shell 中也有系统函数。我们介绍两个抛砖引玉一下:

  • basename,返回文件名
  • dirname,返回路径

test11@pjl:~/tmp$ basename /a/b/c/a.txt a.txt test11@pjl:~/tmp$ basename /a/b/c/a.txt .txt a test11@pjl:~/tmp$ dirname /a/b/c/a.txt /a/b/c shell 综合练习

需求:每天凌晨 3 点备份数据库。

实现如下:

假如 test.txt 就是我们备份完成的数据库:

root@pjl:/home/test11/tmp# ls backup_database.sh test.txt

执行三次写好的备份数据库的脚本:

root@pjl:/home/test11/tmp# bash backup_database.sh DATETIME=2022-06-21_200903 2022-06-21_200903/ 2022-06-21_200903/2022-06-21_200903.txt.gz root@pjl:/home/test11/tmp# bash backup_database.sh DATETIME=2022-06-21_200904 2022-06-21_200904/ 2022-06-21_200904/2022-06-21_200904.txt.gz root@pjl:/home/test11/tmp# bash backup_database.sh DATETIME=2022-06-21_200905 2022-06-21_200905/ 2022-06-21_200905/2022-06-21_200905.txt.gz

我们需要将数据备份到 /data/backup/db/ 目录中,现已生成3个备份:

root@pjl:/home/test11/tmp# ls /data/backup/db/ 2022-06-21_200903.tar.gz 2022-06-21_200904.tar.gz 2022-06-21_200905.tar.gz

最后看一下备份脚本内容:

root@pjl:/home/test11/tmp# cat -n backup_database.sh 1 #!/bin/bash 2 3 # 将数据备份到这 db 目录 4 BACKDIR=/data/backup/db 5 6 # 当前时间 7 # 输出:DATETIME=2022-06-21_110318 8 DATETIME=$(date %Y-%m-%d_%H%M%S) 9 echo DATETIME=$DATETIME 10 11 # 创建备份目录。如果不存在,则创建 12 [ ! -d "${BACKDIR}/${DATETIME}" ] && mkdir -p "${BACKDIR}/${DATETIME}" 13 14 # 备份数据。读取 text.txt 传给 gzip 压缩,在重定向到指定目录 15 cat test.txt | gzip > ${BACKDIR}/${DATETIME}/$DATETIME.txt.gz 16 17 # 将文件处理成 tar.gz 18 cd ${BACKDIR} 19 tar -zcvf $DATETIME.tar.gz ${DATETIME} 20 21 # 删除对应的备份目录 22 rm -rf ${BACKDIR}/${DATETIME}

Tip:${}通常用于划定变量名的边界,例如:

test11@pjl:~$ a=1 test11@pjl:~$ aa=2 test11@pjl:~$ echo $aa 2 test11@pjl:~$ echo ${a}a 1a test11@pjl:~$ echo "${a}a" 1a

栏目热文

sh和s区分不开的原因(s和sh分不清是什么问题)

sh和s区分不开的原因(s和sh分不清是什么问题)

为什么以s,sh,ch,x结尾的可数名词变复数加es而不是s?文中有答案。首先来分析可数名词变复数的规则:可数名词变复数...

2022-10-29 14:53:28查看全文 >>

netsh设置后没反应(电脑输入netsh启动失败)

netsh设置后没反应(电脑输入netsh启动失败)

Win7系统电脑不能连上WiFi网络,网络诊断提示windows无法自动检测此网络的代理设置,该如何解决这个问题?最近有...

2022-10-29 15:18:09查看全文 >>

shsh能修改吗(有了shsh怎么降级)

shsh能修改吗(有了shsh怎么降级)

shell脚本的运行主要分为新建、编辑和执行三个步骤。1、新建脚本文件脚本文件新建可以用touch命令,也可以直接用文本...

2022-10-29 14:54:15查看全文 >>

扩容后可以用shsh恢复系统吗(有了shsh怎么降级)

扩容后可以用shsh恢复系统吗(有了shsh怎么降级)

LINUX raid知识说明:RAID分为软 RAID和硬件 RAID软件 RAID是基于系统的软件工作不稳定,如果系统...

2022-10-29 14:58:19查看全文 >>

shs获取失败的原因(shs查询失败)

shs获取失败的原因(shs查询失败)

通过acme.sh开源工具申请泛解析SSL证书前期准备1.域名2.Linux云服务器(本文系统某讯云的Centos7),...

2022-10-29 14:44:50查看全文 >>

为什么查不到shsh(shsh下载)

为什么查不到shsh(shsh下载)

晨报记者 李星言昨天,上海市教委公布了《2021年本市义务教育阶段学校招生入学工作的实施意见》(以下简称《实施意见》),...

2022-10-29 15:17:15查看全文 >>

shsh如何用(shsh错误怎么解决)

shsh如何用(shsh错误怎么解决)

 用户反馈用记事本打开里面却是空白,接下来给大家分享win7系统打开shs文件步骤。  1、右击鼠标,选择新建-Micr...

2022-10-29 14:43:14查看全文 >>

做阴镜和活检一样吗(做阴镜活检痛苦吗)

做阴镜和活检一样吗(做阴镜活检痛苦吗)

阴道镜和活检是妇科大夫常用的检查手段,但是不少患者对于阴道镜和活检会有疑惑和恐惧心理。门诊上经常会有患者咨询:做阴道镜疼...

2022-10-29 14:55:21查看全文 >>

阴镜活检结果有哪几种(做阴镜活检过程疼吗)

阴镜活检结果有哪几种(做阴镜活检过程疼吗)

宫颈癌是常见的恶性肿瘤,不少小姐姐一想到它就觉得心惊胆战,纷纷在体检中加入宫颈癌筛查项目。可是拿到检查报告时,却发现如阅...

2022-10-29 15:04:10查看全文 >>

什么情况需要做阴镜活检(活检报告单的最坏结果)

什么情况需要做阴镜活检(活检报告单的最坏结果)

很多网络咨询患者在询问病情的时候,会上传检查图片给我看,宫颈检查报告是其中的重要检查,但从这些图片中,我也发现有一个“普...

2022-10-29 15:04:13查看全文 >>

文档排行