关于Linux操作系统中当前shell进程与子shell进程的详细解释
如上图所示,使用ps -f可以当前查看Linux操作系统中当前正在运行的进程。
然后敲bash后,相当于在当前的bash shell环境下又创建了一个子bash shell的进程,
如上图所示,后来创建的bash shell的PPID是前一个bash shell的PID
使用./hello.sh的方式去调用脚本就相当于是在原来bash shell的基础上又开了一个子bash shell,然后在子bash shell中去调用脚本。
敲exit命令时会发现没有退出Linux操作系统就在于当前是在子shell进程中,
开子shell与不开子shell的区别就在于,环境变量的继承关系,如在子shell中设置的当前变量,父shell中是不可见的。
系统预定义变量
在shell编程中存在系统变量和用户变量,其中系统变量的作用范围是全局,而用户变量的作用范围却是分为全局变量和局部变量。
局部变量是只对当前的bash起效。
Linux操作系统中shell编程的系统变量大部分是全局变量,小部分是局部变量。
$HOME表示当前用户的家目录,$PWD表示当前用户的工作目录,$SHELL表示当前的shell会话,$USER表示当前的用户,
如果想查看当前所有的全局环境变量的话,就是用env,printenv的功能和普通的env大致是一样的。
如果想使用系统变量,就使用echo或者printenv加系统变量。
如上图所示,如果只是想查看当前系统变量的值的话,加不加$符无所谓但是如果想使用系统变量的值的话,就必须加上$了。
在Linux操作系统中可以使用set命令可以用来显示当前所有的shell变量(包括环境变量)及其值。
用户的自定义变量
如上图所示,在Linux操作系统中shell编程语言中关于用户变量的定义只需要变量名=变量值,就可以直接定义变量,不需要像其他编程语言一样去定义变量的类型再去给变量赋值,如果变量值中有空格就需要我们将将变量值用引号引起来才能生效,这时定义的变量属于用户变量中的局部变量,即在原来的bash环境中有,在子bash中没有,
可以使用set | grep my_var这样的命令来查找用户创建的变量的值,
如上图所示,在新创建的子bash中,echo $my_var发现不输出变量的值,这就说明用户创建的my_var是一个局部变量。
如上图所示,在子bash中找不到用户创建的变量的值,但是退出子bash后,可以查找到用户创建的变量的值,说明这时一个用户变量中的局部变量,如果像把局部变量定义成全局变量的话,如下图操作。
如上图所示,如果我们想定义一个全局变量它的作用范围是在-bash以及嵌套的bash中有效,
这就需要使用export 变量名称,来将用户创建的局部变量定义为一个全局变量,这时再创建一个bash环境,进入到这个子bash环境时,echo 变量名称,发现变量的值就可以输出打印了。
如果在子bash中对这个变量进行变量值的修改时,再进入到别的bash环境中,就发现原来变量的值并没有改变,
所以对这个全局变量的修改只在修改界面中的bash中有效,在其他的bash环境中对变量的修改操作无效。当然如果在子bash中对变量进行更改后,使用export 变量名称,这时子bash包括它嵌套的子bash中修改的变量值都是可以看到的。
如上图所示,在子bash中对全局变量进行数值修改以后,再将变量重新定义为全局变量时,切换到-bash环境中依然看不到对变量的修改操作,所以在子bash中对变量进行更改后,使用export 变量名称,这时子bash包括它嵌套的子bash中修改的变量值都是可以看到的。但是在子bash以外的bash环境中看不到对变量的修改操作。
在不同bash环境中对脚本的调用
如上图所示,在脚本hello.sh中加上了一个变量,当调用这个脚本的时候,就可以打印输出这个变量的值,而随着调用脚本的bash环境不同,其调用脚本的结果也不同,当使用source 调用脚本的时候,bash环境是当前的bash环境,而使用./hello.sh来调用脚本的时候,bash环境就是当前bash环境的子bash环境,
这时定义一个用户变量中的局部变量,然后在脚本hello.sh中添加这个变量,发现在当前bash环境中的子bash环境中这个局部变量是不生效的。而如果以. hello.sh或者source hello.sh来在当前bash环境中调用这个脚本局部变量就可以生效。
如果使用export 局部变量名称,这时该局部变量就变成了全局变量,这时再使用./hello.sh(在当前bash环境下启动一个子bash,或者给脚本添加x执行权限,直接通过调用脚本路径的方式来调用脚本)这样的方式来调用脚本,该脚本中的两个变量都生效。
全局变量,只读变量和撤销变量
如上图所示,使用echo 加变量名称,就可以打印变量值,对于shell编程来说,变量名=变量值,这期间没有能对变量值进行运算的操作,如果想对变量值进行运算就需要使用a=$[5+9]或者是a=$((1+5))这样的操作。
这里是关于shell编程的运算符的介绍,
只读变量
这里的意思就是说定义一个常量,此时这个变量中的变量值只能进行读的操作,不能对这个变量值进行修改。
如上图所示,这是在定义一个只读变量,使用readonly 变量名称=变量值,这就是在shell中定义了一个只读变量,如果此时想修改这个变量的变量值,就会被提醒,这是一个只读变量,不能进行对变量值的修改操作。
撤销变量
如上图所示,如果你想撤销一个变量的话,直接unset 变量名,就可以将该变量撤销掉,撤销变量的意义在于该变量没有用处时,撤销掉,节省内存空间。
在shell编程中如果将一个变量定义为一个只读变量,此时直接用unset 变量名称,是不可以撤销这个只读变量的,需要先将这个只读变量的只读状态撤销掉。
如果你确实需要“撤销”这个只读状态,可以采取以下策略之一:
-
重新声明变量:你可以在新的Shell作用域中重新声明这个变量,这样就绕过了原来的只读限制。这通常意味着在子shell中或者一个新的脚本进程中来做这件事,因为父shell中的只读属性不会传递给子进程。
Bash1# 在子shell中重置变量 2( 3 myVar="New Value" 4 echo "$myVar" # 输出 "New Value" 5) 6echo "$myVar" # 回到父shell,输出仍是 "Hello World"
-
使用unset后再重新赋值:注意,
Bashunset
命令可以删除一个变量,包括只读变量,但这仅在该变量不是全局只读变量时有效。之后,你可以重新声明该变量。但请注意,这实际上是“删除并重新创建”,而非直接撤销只读属性。1# 如果变量不是全局只读,可以先unset再赋值 2unset myVar 3myVar="New Value"
-
避免使用
readonly
:在设计脚本时,如果预见需要改变变量的值,最初就不要将其声明为只读。
由于Shell中没有直接撤销只读属性的命令,理解和规划你的脚本结构以适应这种限制是很重要的。在大多数情况下,只读变量是用来防止意外修改关键数据的,因此撤销只读状态应当谨慎考虑其必要性。
如何将脚本当作命令一样去使用呢?(前提在不改变/bin/目录内容的前提下.)
如上图所示,可以将脚本的名称cp 复制到/bin/下,此时对于脚本的调用就可以像正常的命令一样,但是/bin/是Linux操作系统储存命令shell脚本的地方,特别不建议对/bin/中的内容进行修改。
如上图所示,可以将脚本的名称复制到/root/bin目录中,这样就可以将该脚本的调用当成像命令一样了,或者直接将脚本的绝对目录加入到/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin中,这样对脚本的调用也可以像命令的调用一样了。
[root@localhost ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost ~]#
对于脚本来说,如何给脚本加参数?
对于脚本来说,这个脚本的作用对象不同,给传递给脚本的参数也不相同。
在Linux操作系统中对参数的获取。这里的$数字参数,主要是位置参数。
如上图所示,当你想在调用脚本的时候,给脚本传递相应的参数的话,就需要在脚本中编写的时候,加入相应的变量来储存参数,比如$1这样的变量。
如上图所示,在编写脚本后记得给脚本添加上可执行权限,
script name:可以直接输出此时调用脚本的路径,
1st paramater :$1 这里的$1用来承接变量1
2nd paramater:$2这里的$2用来承接变量2
在Linux操作系统中对参数的获取,这里的$n参数,主要作用是统计系统传给脚本的参数的个数。
如上图所示,parameter numbers:2 表示当前系统传给脚本的参数个数是两个。
在Linux操作系统中对参数的获取,这里的$*和$@参数,$*的主要作用是代表命令行中所有的参数,$*把所有的参数看成是一个整体,$@把每个参数区分对待。
$*获取到的像是一个整体比如abc def
$@获取到的像是一个数组,比如[abc,def] 这里的$@获取到的结果像是一个数组,此时就可以使用循环去遍历里面的参数,
在Linux操作系统中对参数的获取,$?的作用是返回最后一次执行脚本的
$?这个特殊变量用来储存执行命令之后的返回值,如果返回值是0则表示上一条命令执行成功。
如上图所示,当一个命令执行成功的时候,此时敲命令 echo $?系统返回数字0表示命令执行成功,
当一个命令执行失败的时候,此时敲命令echo $?系统返回数字127表示命令执行失败。
注意在shell编程中使用单引号包围字符串和使用双引号包围字符串的时候有什么区别?
在Shell编程中,当你使用单引号('
)包围字符串时,Shell会原样输出字符串内的内容,不做任何变量替换或特殊字符处理。所以,如果你写了 echo '======$n======'
,Shell会将$n
视为字符串中的文字字符,而不是一个变量引用。它会原封不动地输出 ======$n=====
, 而不会尝试去替换$n
为它可能代表的变量值。
如果你想让Shell解析 $n
作为变量,并显示其值(假设之前已定义),你应该使用双引号("
):
Bash
1echo "======$n======"
在双引号中,Shell会执行变量扩展、命令替换等操作,因此如果之前有定义变量 n
,它的值就会被正确地插入到字符串中输出。