最近在学习《Linux命令行和shell脚本编程大全》(第四版)这本书,对于自己遇到的问题以及通过搜索引擎和书籍中的解决方案进行一个案例的剖析,希望对于像我这样的初学者,有一个帮助。
问题其实都相对简单,但是如果这些点大家不了解,可能还真的会将大家从Shell编程入门直接扼杀到放弃了。
1、 command not found
报错问题
1.1 command not found
报错背景
在《第12章结构化命令》中第12.4.3一节中有这样的一个类似例子
代码语言:shell复制#!/bin/bash
directory=/home/jiangms/linux_cmd
file=linux_test.sh
if [ -d $directory ]
then
echo "OK,on the $directory directory"
echo "Now checking on the file ,$file..."
if [ -e $directory/$file ]
then
echo "$file exists"
cd $directory
ls -l >> log.$(date %y%m%d) # ***
else
echo "$file doesn't exist"
fi
else
echo "$directory doesn't exist"
fi
因为为了更多的举一反三,我将其中的一段带 ***
脚本替换为ll
,因为我平时使用这个脚本的频次最高,但是报错如下:
[root@iZuf6gxtsgxni1r88kx9rtZ linux_cmd]# sh file_exist.sh
OK,on the /home/jiangms/linux_cmd directory
Now checking on the file ,linux_test.sh...
linux_test.sh exists
file_exist.sh: line 12: ll: command not found
这个报错令人猝不及防
1.2 报错解决方式
通过文心一言的提问,发现问题很简单,因为ll
为一个ls -l
的别名,而系统中如果没有定义ll
命令,当你尝试ll
命令的时候,就会报错ll: command not found
。
方法一、我按照网上的做法去path = ./etc/bashrc
中增加了配置alias ll='ls -l'
重启后依然无效,这种做法可能对我这个问题暂时无效或者我处理的有问题,如果读者有清楚的可以跟我交流,一起把这个文章补充完整。
方法二、就是将ll
改成ls -l
非别名的形式,重新运行,脚本正常运行,成功解决问题。
2、 Shell脚本的内部变量
在《第12章结构化命令》中第12.6.1一节中,讲述if-then的高级特性有这样的一段脚本
代码语言:shell复制$ cat SingleParentheses.sh
#!/bin/bash
# Testing a single parentheses condition
#
echo $BASH_SUBSHELL
#
if (echo $BASH_SUBSHELL)
then
echo "The subshell command operated successfully."
#
else
echo "The subshell command was NOT successful."
#
fi
$
$ ./SingleParentheses.sh
01
The subshell command operated successfully.
$
这里主要的意思是说,在if-then结构中,(command)
命令中不需要重启一个父shell,而是直接运行一个子shell,而它的父shell是SingleParentheses.sh
的shell。
但是这里有一个问题:$BASH_SUBSHELL
是什么东西?前面没有铺垫,后面没有注释,难道作者是想要通过一个空的命令来假装验证?但是我在前面的章节中也知道,很多的系统变量都喜欢用英文大写字母来定义,比如说HOME
、PATH
、IFS
等,但就是没有想到$BASH_SUBSHELL
也是一个系统的内部变量。
而它的含义是:该变量用于提示所处的 subshell 层级。但是这么说又有点抽象,看下面的例子:
例子1:
代码语言:shell复制[root@iZuf6gxtsgxni1r88kx9rtZ linux_cmd]# (echo hello world;(echo $BASH_SUBSHELL))
hello world
2
例子2:
代码语言:shell复制[root@iZuf6gxtsgxni1r88kx9rtZ linux_cmd]# (echo hello world;(echo $BASH_SUBSHELL;(echo $BASH_SUBSHELL)))
hello world
2
3
例子3:
代码语言:shell复制[root@iZuf6gxtsgxni1r88kx9rtZ linux_cmd]# (echo hello world;(echo $BASH_SUBSHELL);(echo $BASH_SUBSHELL))
hello world
2
2
第一个例子显示2,代表了echo $BASH_SUBSHELL
为第二层的子shell;第二个例子中第一个$BASH_SUBSHELL
为第二层子shell,而第二个$BASH_SUBSHELL
为第三层的子shell;第三个例子中的两个$BASH_SUBSHELL
为同一层级的且均为第二层子shell。相信这样解释大家应该对$BASH_BUBSHELL
有了一定的了解,也不会不认识这个内部变量了吧!!!
而关于shell脚本的内部变量的具体说明,大家可以看看文末的参考文献,个人觉得是比《Linux命令行和shell脚本编程大全》书中解释的更清晰。
3、参考文献
- Shell进阶脚本-内部变量
我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!
我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!