Shell是一种计算机操作系统的外壳或命令解释器,它提供了用户与操作系统内核进行交互的方式。用户可以通过Shell执行命令,启动程序,管理文件和目录,以及进行各种系统操作。
Shell可以以交互模式或批处理模式运行。在交互模式中,用户可以直接在Shell中输入命令,并立即查看结果。而在批处理模式中,用户可以将一系列的命令写入脚本文件,然后通过执行脚本文件一次性地运行这些命令,这对于自动化任务非常有用。
常见的Shell有许多种,如Bash(Bourne Again Shell)、sh(Bourne Shell)、csh(C Shell)、ksh(Korn Shell)等。不同的Shell具有不同的语法和功能,但它们的基本原理和作用都是相似的。
shell是一块包裹着系统核心的壳,处于操作系统的最外层,与用户直接对话,把用户的输入,解释给操作系统,然后处理操作系统的输出结果,输出到屏幕给与用户看到结果。
Shell的作用可以总结为以下几个方面:
1. 命令执行:Shell允许用户通过输入命令来执行各种操作系统的功能和程序。用户可以运行系统命令、启动应用程序、管理文件和目录等。
2. 程序脚本:Shell提供了脚本编程的功能,用户可以编写一系列的命令和逻辑,存储为脚本文件,并通过Shell解释器执行。这样可以实现自动化任务、批处理操作,提高工作效率。
3. 环境配置:用户可以通过Shell配置和管理系统的环境。例如,设置系统变量、定制命令别名、配置默认编辑器等。这样可以根据个人需求和习惯来调整系统的行为和外观。
4. 输入输出重定向:Shell提供了重定向功能,可以将命令的输入从键盘改为文件,将输出保存到文件中,或者将命令的输出作为其他命令的输入。这样可以方便地进行文件操作、数据处理和管道操作。
5. 权限控制:Shell可以通过访问控制机制管理用户对系统资源的访问权限。例如,在使用Shell执行命令时,系统会检查用户的权限,只允许具有足够权限的用户执行特殊的操作。
总而言之,Shell是用户与操作系统内核进行交互的接口,提供了执行命令、编写脚本、配置环境、管理权限等功能,使用户能够更自由地使用和控制计算机系统。
·命令行操作,shell解释执行后,输出结果到黑屏命令行界面
·图形化操作,shell接受点击动作,输出图案数据
shell命令:由C语言编写后,gcc编译成二进制文件,存储在usr/bin目录,通过shell命令和shell解释器调用文件;
当命令或者程序语句写在文件中,我们执行文件,读取其中的代码,这个程序文件就称之为shell脚本。在shell脚本里定义多条Linux命令以及循环控制语句,然后将这些Linux命令一次性执行完毕,执行脚本文件的方式称之为,非交互式方式。
- windows中存在*.bat批处理脚本
- Linux中常用*.sh脚本文件
shellj脚本规则:
在Linux系统中,shelI脚本或者称之为(bash shell程序〉通常都是vim编辑,由Linux命令、bash shell指令、逻辑控制语句和注释信息组成。
# !/bin/sh
echo "我是一个shell脚本"
计算机程序中,shebang指的是出现在文本文件的第一行前两个字符#!在Unix系统中,程序会分析 shebang后面的内容,作为解释器的指令,例如
·以#!/bin/sh开头的文件,程序在执行的时候会调用/bin/sh ,也就是bash解释器
·以# !/usr/bin/python开头的文件,代表指定python解释器去执行
·以# ! /usr/bin/env 解释器名称,是一种在不同平台上都能正确找到解释器的办法
inux的which命令用于查找给定的命令在哪个目录下执行。它会在系统的 PATH 环境变量所设置的目录中查找给定命令的可执行文件,并返回第一个找到的路径。如果找不到该命令,则会返回错误信息。
注意事项:
1.如果脚本未指定shebang ,脚本执行的时候,默认用当前shell去解释脚本,即 $SHELL
2.如果 shebang 指定了可执行的解释器,如/bin/bash或/usr/bin/python ,脚本在执行时,文件名会作为参数传递给解释器
3.如果#!指定的解释程序没有可执行权限,则会报错bad interpreter: Permission denied”。
4.如果#!指定的解释程序不是一个可执行文件,那么指定的解释程序会被忽略,转而交给当前的SHELL去执行这个脚本。
5.如果#!指定的解释程序不存在,那么会报错"bad interpreter: No such file or directory”。
6.#之后的解释程序,需要写其绝对路径(如:#!/bin/bash),它是不会自动到$PATH中寻找解释器的。7.如果你使用"bash test.sh"这样的命令来执行脚本,那么#!这一行将会被忽略掉,解释器当然是用命令行中显式指定的bash。
1.bash hello.sh 或 sh hello.sh ,文件本身没权限执行,没x权限,则使用的方法,或脚本未指定shebang ,重点推荐的方式,属于/bin/sh hello.sh的简化形式。
代码实例:
[root@iZ2zeg0eyon02gbtl3sldpZ c]# cat hello.sh
# !/bin/sh
echo "我是一个shell脚本"
[root@iZ2zeg0eyon02gbtl3sldpZ c]# sh hello.sh
我是一个shell脚本
[root@iZ2zeg0eyon02gbtl3sldpZ c]# cat hello.sh
# !/bin/sh
echo "我是一个shell脚本"
[root@iZ2zeg0eyon02gbtl3sldpZ c]# bash hello.sh
我是一个shell脚本
2.使用绝对/相对路径执行脚本,需要文件含有x权限
代码实例:
[root@iZ2zeg0eyon02gbtl3sldpZ c]# chmod +x hello.sh
[root@iZ2zeg0eyon02gbtl3sldpZ c]# ./hello.sh
我是一个shell脚本
3.source hello.sh或者. hello.sh ,代表执行的含义,source等于点.。需要注意的是,此种方法是在当前shell中执行,其余都是创建子shell执行。
代码实例:
[root@iZ2zeg0eyon02gbtl3sldpZ c]# cat hello.sh
# !/bin/sh
echo "我是一个shell脚本"
[root@iZ2zeg0eyon02gbtl3sldpZ c]# source hello.sh
我是一个shell脚本
4.少见的用法,sh < script.sh,重定向
代码实例:
[root@iZ2zeg0eyon02gbtl3sldpZ c]# sh < hello.sh
我是一个shell脚本
[root@iZ2zeg0eyon02gbtl3sldpZ c]# bash < hello.sh
我是一个shell脚本
. bash是一个命令处理器,运行在文本窗口中,并能执行用户直接输入的命令. bash还能从文件中读取linxu命令,称之为脚本
. bash支持通配符、管道、命令替换、条件判断等逻辑控制语句
history | 查看历史命令 |
echo $HISTSIZE | 查看历史命令数目 |
vim ~/.bash_history | 打开存储文件 |
echo $HISTFILE | 显示历史文件路径 |
history -c | 清空历史命令(文件不改变) |
history -r | 恢复历史命令 |
!历史id | 快速执行历史命令 |
!! | 执行上次历史命令 |
bash特性汇总
1.文件路径tab键补全·命令补全
2.快捷键ctrl + a,e,u,k,h3·通配符
4·命令历史5·命令别名
6·命令行展开
变量定义和取值方式:
[root@iZ2zeg0eyon02gbtl3sldpZ c]# name="我是变量"
[root@iZ2zeg0eyon02gbtl3sldpZ c]# echo ${name}
我是变量
[root@iZ2zeg0eyon02gbtl3sldpZ c]# echo $name
我是变量
${name},表示完整取值,大括号可以省略
本地变量中,子shell和父亲shell完全隔离,切换shell变量会丢失。
pstree是一种命令行工具,用于显示进程树。它可以显示当前系统中所有进程的层次结构,以及它们之间的父子关系。通过使用pstree命令,用户可以更好地了解系统中正在运行的进程,并且可以更轻松地诊断和解决问题。
单引号变量:不识别特殊语法
双引号变量:能识别特殊语法
代码实例:
#单引号
[root@iZ2zeg0eyon02gbtl3sldpZ c]# name="tom"
[root@iZ2zeg0eyon02gbtl3sldpZ c]# name1='$name'
[root@iZ2zeg0eyon02gbtl3sldpZ c]# echo $name1
$name
#双引号
[root@iZ2zeg0eyon02gbtl3sldpZ c]# name2="$name"
[root@iZ2zeg0eyon02gbtl3sldpZ c]# echo $name2
tom
1.每次调用bash/sh解释器执行脚本,都会开启一个子shell,因此不保留当前的shell变量,之前定义的变量还在。通过pstree命令检查进程树
2.调用source是在当前shell环境加载脚本,因此保留变量(.sh文件中定义的变量,保存到当前shell中)
sh | 进入子shell |
bash | 进入子shell |
exit | 退出bash |
环境变量:也叫全局变量,针对当前shell以及任意子进程,环境变量也分为自定义,内置两种环境变量。
局部变量:针对shell脚本或shell函数中定义
位置参数变量:ls -l /opt -l和opt都是位置参数变量
$?:判断上一条命令是否成功
0:成功
1-255:失败
代码实例:
[root@iZ2zeg0eyon02gbtl3sldpZ ~]# cd ..
[root@iZ2zeg0eyon02gbtl3sldpZ /]# echo $?
0
[root@iZ2zeg0eyon02gbtl3sldpZ /]#
在linux中反引号,中的命令执行结果会被保留下来
代码实例:
[root@iZ2zeg0eyon02gbtl3sldpZ c]# name=`ls`
[root@iZ2zeg0eyon02gbtl3sldpZ c]# echo $name
hello.sh hellow.sh
环境变量一般指的是用export内置命令导出的变量,用于定义shell的运行环境、保证shell命令的正确执行。shell通过环境变量确定登录的用户名、PATH路径、文件系统等各种应用。
环境变量可以在命令行中临时创建,但是用户退出shell终端,变量即丢失,如要永久生效,需要修改环境变量配置文件
·用户个人配置文件 ~/.bash_profile 、 ~/.bashrc远程登录用户特有文件
·全局配置文件/etc/profile 、/etc/bashrc ,且系统建议最好创建在/etc/profile.d/ ,而非直接修改主文件,修改全局配置文件,影响所有登录系统的用户
环境变量:能找出linux服务器上,各种变量
useradd name | 增加用户 |
passwd name | 给用户设置密码 |
su - name | 切换用户 |
pwd | 查看绝对路径 |
在~/.bash_profile 、 ~/.bashrc加入export name="cao"后,重新登录该用户,就可以得到环境变量name,不论在哪一个shell中,都可以访问。但是其它用户访问不到。
在/etc/profile 、/etc/bashrc中加入name="cao"后,重新登录该用户,既可以得到全局配置的环境变量,在所有用户都可以访问,重名时比用户优先级低。
set | 输出所有变量,包括全局和局部(当前shell) |
env | 只显示全局变量 |
declare | 输出所有变量 |
export | 显示和设置环境变量值 |
unset 变量名 | 删除变量或函数 |
readonly | 只读变量,shell结束后失效 |
set | wc -l 显示set命令有多少行
set | grep ^name 查找以name开头的环境变量
bash多命令用“;”隔开
取出变量值:
·单引号,所见即所得,强引用
·双引夸,输出引号里所有内容,识别特殊符号,弱引用
·无引号,连续的符号可以不加引号,有空格则有歧义,最好使用双引号。反引号,引用命令执行结果,等于$()用法
$0:获取shell脚本文件名,以及脚本路径
$n:获取shell脚本的第n个参数, n在1~9之间,如$1 ,$2,$9 ,大于9则需要写,${10},参数 空格隔开
$# :获取执行的shel脚本后面的参数总个数4
$*:获取shel1脚本所有参数,不加引号等同于$@作用,加上引号"$*"作用是接收所有参 数为单个字符串,"$1$2..$@ :不加引号,效果同上,加引号,是接收所有参数为独立字符串,如"$1"“$2”“$3”...,空格 保留
ls -l
#-l 参数
text.sh
sh text.sh 参数1 参数2 参数3
$*和$@的区别你了解吗?
$*和$@都表示传递给函数或脚本的所有参数
当$*和$@不被双引号”"包围时,它们之间没有任何区别,都是将接收到的每个参数看做一份数据,彼此之间以空格来分隔。
但是当它们被双引号"“包含时,就会有区别了:
"$*"会将所有的参数从整体上看做一份数据,而不是把每个参数都看做─份数据。“$@"仍然将每个参数都看作一份数据,彼此之间是独立的。
比如传递了5个参数,那么对于""$*"来说,这5个参数会合并到一起形成一份数据,它们之间是无法分割的;而对于$@"来说,这5个参数是相互独立的,它们是5 份数据。
如果使用echo直接输出$*"和"$@"”做对比,是看不出区别的﹔但如果使用for 循环来逐个输出数据,立即就能看出区别来。
shell for循环
代码:
#!/bin/bash
echo "print each param from \"\$*\""
for i in "$*"
do
echo "$i"
done
echo "print each param from \"\$@\""
#\转译
for i in "$@"
do
echo "$i"
done
#do代表循环体开始,done代表循环体结束
结果:
[root@iZ2zeg0eyon02gbtl3sldpZ c]# sh diffent.sh a b c d
print each param from "$*"
a b c d
print each param from "$@"
a
b
c
d
$?: 上一次命令执行状态返回值,0正确,非0失败
$$: 当前shel1脚本的进程号(PID)
$!: 上一次后台进程的PID
$_: 取得上一次命令,最后一个参数
查找方式: man bash
搜索: Special Parameters
nohup xxxx & 1> /dev/null 程序后台运行,日志写入黑洞文件
echo
-n 不换行输出
-e 解析字符串中的特殊符号(\n 换行 \r 回车 \t 制表符 \b退格)
eval 执行多个命令
eval ls;cd ..
exec
不创建子进程,执行后续命令,且执行完后自动exit
expr数值计算
expr length "${name}" 统计变量长度
${变量} 返回变量值
${#变量} 返回变量长度,字符长度
${变量:start} 返回变量start数值之后的字符
${变量:start : length} 提取startt之后的length限制的字符
${变量#word} 从变量开头删除最短匹配的word子串 //本值不变
${变量##word} 从变量开头,删除最长匹配的word
${变量%word} 从变量结尾删除最短的word
${变量%%word} 从变量结尾开始删除最长匹配的word
${变量/pattern/string} 用string代替第一个匹配的pattern${变量//pattern/string} 用string代替所有的pattern
echo ${name} | wc -l 显示行数
echo ${name} | wc -L 显示最长的一行的个数
echo "${name}" | awk '{print length($0)}' //个数
shell编程,尽量使用linux内置的命令,内置的操作,和内置的函数,效率最高c语言开发,效率最高,尽可能的减少管道符的操作
#从开头删除匹配最短
##开头删除匹配最长
%从结尾删除匹配最短
%%从结尾删除匹配最长
指定字符内容截取
a*c匹配开头为a,中间任意个字符,结尾为c的字符串a*C匹配开头为a,中间任意个字符,结尾为c的字符串
如果parameter变量值为空,返回word字符串,赋值给result变量
result=${parameter : -word}
如果para变量为空,则word替代变量值,且返回其值result=${parameter :=word}
如果para变量为空,word当作stderr输出,否则输出变量值用于设置变量为空导致错误时,返回的错误信息
${parameter : ?word}
如果para变量为空,什么都不做,否则word返回${parameter : +word}
ps -ef --forest //显示进程和shell详细信息
shell的进程理念,需要使用()小括号
source和.执行脚本,是在当前的shell中执行
Linux默认有关的shell变量
BASH_SUBSHELL
0代表在当前shell执行的,否则是开辟子shell执行的,1代表子shell,2代表孙shell
():开启子shell运行
linux内置命令,外置命令
内置命令:在系统启动时就加载入内存,常驻内存,执行效率高,但是占用资源,cd
外置命令:用户需要从硬盘中读取程序文件,再读入内存加载/bin /usr/bin /sbin usr/sbin
外置命令特点:效率低一些,并且一定会开启子进程执行
内置命令特点:不会产生子进程,和shell是一体的,不需要单独读取某个文件,系统启动后,就执行在内存中了。
内置命令查看:compgen -b
shell的一些基础命令,只支持整数的运算,小数的计算需要如bc这样的命令才支持
· ·:反引号,执行命令后,放到字符串和$()相同
who命令:查看用户登录时间和用户名
${var}:取出变量结果的
$():在括号中执行命令,且拿到命令的执行结果
(()):进行数值运算
exit :返回一个状态码
奇奇怪怪的使用算法
Let命令执行:
let命令的执行,效果等同于双小括号,但是双小括号更加高效,左移右移要加转移符
expr命令执行:
expr:简单计算器,必须是以传入参数的形式
:冒号,计算字符串的字符数量(字节),支持通配符
bc计算器:
bc交互式的操作,支持小数的计算
bc结合管道符:
案例:
计算1-1000的和
tr是替换
seq是生成数列
awk计算:
支持小数计算,
$[表达式]:
test命令评估一个表达式,它的结果是真,还是假,如果条件为真,那么命令执行状态码结果就为0否则就是不为0,通过$?取值;
shutdown语法:
# 语法 shutdown -h 小时:分钟
# 示例,晚上十点半自动关机
shutdown -h 22:30
text和[ ]的作用是一样的,注意中括号前后都要有空格,条件测试中使用变量,必须添加双引号。
双中括号:[[ ]]
支持正则,并且&&和||,<,>可写在内部,[ ]不支持正则通配符,&&和||不能写在里面。
注意:!也是一个操作符,取反的意思
字符串变量的比较,一定要加入双引号。操作符两边一定要有空格
[]和test:
在中括号中,使用数学比较符号,请添加转义符号。!=不用加
变量的话要加双引号
text和[ ]支持,-eq此类写法,也支持>,<等。
双中括号:
对单中括号的补充,支持正则表达式,且不需要转义符号
[[ ]]支持,-eq此类写法,也支持>,<等
逻辑判断符号:
&& -a 与运算,两边都为真,才为真
|| -o 或运算,两边有一个为真,就为真
中括号逻辑运算比较:
单个中括号内不能使用&&和||
双中括号可以使用
cat还能这样使用。
if <条件表达>
then
代码
elif <条件表达>
then
代码
...fi
当使用function关键字时,可以省略括号
当函数的定义和执行分开不在一个文件时,
手动:
脚本: