Linux Shell基线配置高级操作
一、输入解析类
1.1 echo解析tab和换行
问题描述:echo默认是原样输出字符串,并不解析\t和\n等反斜杠字符,如下图所示。我们希望echo能解析\t和\n等字符。
处理办法:可以使用-e指示echo识别反斜杠。
1.2 cat将变量写入文件
问题描述:我们经常需要将变量写到配置文件,比如将java相关的几个变量写到~/.profile,追加多行cat是最方便的但cat默认会在插入时解析变量,如下图所示。我们希望就是原样写入而不自动解析变量。
处理办法:可通过给EOF加上单引号来指示cat不要解析变量。
参考:https://blog.csdn.net/u010154760/article/details/45955797
1.3 while语句中修改变量值
问题描述:我们知道shell中的变量是全局的,但如果注意会发现有时在while语句内修改变量值并不生效。如下所示,我们想用while语句统计/etc/passwd中的用户数量,但user_count最后依然是0。
user_count=0
cat /etc/passwd | while read line
do
user_count=`expr $user_count + 1`
done
echo $user_count
处理办法:造成这种情况的原因是while针对数据从管道传输过来这种方式,会启动一个子shell去处理,在子shell中修改参数并不能影响当前shell中的参数的值(相当于函数中的传值)。解决办法是换一种while就在当前shell中处理的写法。
user_count=0
while read line
do
user_count=`expr $user_count + 1`
done <<< "$(cat /etc/passwd)"
echo $user_count
参考:https://stackoverflow.com/questions/16854280/a-variable-modified-inside-a-while-loop-is-not-remembered
1.4 Windows换行转Linux换行
问题描述:Windows换行是“\r\n”,而Linux换行是“\n”;Windows上的编写shell文件直接传到Linux系统上运行会报错“$’\r’: command not found”(用vim打开文件会看到行尾是^M),此时需要将“\r”删除。
处理办法:
shell脚本文件已传到Linux上使用sed删除——sed -i -r ‘s/\r$//g’ file_name
shell脚本文件还在Windows上使用Notepad++编缉器转换——菜单——编缉——文档格式转换——转换为Unix格式
sehll脚本由python3动态生成——打开文件时使用newline指定生成文件的换行符,如file_obj = open(“test.sh”,”w+”,encoding=”utf-8”,newline=”\n”)
参考:https://www.zhihu.com/question/19751023
另附pycharm指定行分格符的方法——与上边说的shell脚本换行无关,即便pycharm指定换行符为“LF”不通过newline指定动态生成的文件换行符依然是“\r\n”——分以下三类情况讨论
修改单个文件换行符——pycharm打开文件并切换到该文件——右下角有当前页面的换行符,在其上点击切换为“LF - Unix and OS X (\n)”
修改文件夹下所有文件换行符——pycharm打开项目——在工程窗口使用光标选中要修改换行符的文件夹——菜单——File——Line Separators——“LF - Unix and OS X (\n)”
指定后续新建文件换行符(不影响已有文件)——菜单——File——Setting——Code Style——Line separator——设置为“Unix and OS X (\n)”
参考:https://www.jetbrains.com/help/pycharm/configuring-line-endings-and-line-separators.html
二、输出查找类
2.1 tail读取指定行后内容
问题描述:我们可以用tail配合-n指定读取文件最后多少行,但如果文件是不定长的而我想读取第1行以后的所有行,这个场景该怎么实现呢。
处理办法:其实-n除了直接接数字还,可以在数字前使用“+”号表示从第几行开始读取。(head的-n有类似的操作head -n -2即表示读取到倒数第二行)
2.2 grep查找进程并过滤查找命令本身
问题描述:我们经常使用ps -ef | grep something的语句去查找进程(以便进一步获取pid等),但此时grep本身也会被打印出来,如下图所示。我们希望grep语句本身也被过滤掉。
处理办法:使用grep -v grep将grep语句去掉
2.3 grep打印匹配行的前后几行
问题描述:我们使用grep查找时默认只打印匹配行,这种实现是合理的,但有时候匹配行与前后部份是强关联的我们也想获取。
处理办法:我们可以使用-A num指示打印匹配行的后几行,使用-B num指示打印匹配行的前几行。
2.4 sed去除块注释
问题描述:在读取tomcat等配置文件时,如果只是直接grep那查找出的内容可能其实是在块注释之中,该项配置其实并不生效。我们希望能先将配置文件中先将所有注释先去除掉。
处理办法:此时可以使用sed ‘/regex/d’删除单行注释,使用sed ‘/star_line_regex/,/end_line_regex/d’来删除掉块注释(d换成p就可用作查找块)。具体到tomcat如下
cat tomcat-users.xml |sed '/<!--.*-->/d' | sed '/<!--/,/-->/d'
参考:https://askubuntu.com/questions/525974/how-to-remove-comments-from-an-xml-file
1.4 将字符串作为命令执行
问题描述:在shell脚本中我们有时希望使用一个变量保存要执行的命令,再用一个变量保存命令执行后得到的结果。在如下形式中我们需要写两遍命令,这是不符合复用思想的。
# 变量command保存要执行的命令pwd;第一次写pwd
command="pwd"
# 变量result保存要执行的命令pwd的结果;再次写pwd
result=`pwd`
处理办法:我们可以使用eval命令,将command变量中保存的字符串作为命令执行,代码如下。
# 变量command保存要执行的命令pwd;第一次写pwd
command="pwd"
# 变量result保存要执行的命令pwd的结果;使用eval $command代替再次敲写命令pwd
result=`eval $command`
参考:https://stackoverflow.com/questions/2005192/how-to-execute-a-bash-command-stored-as-a-string-with-quotes-and-asterisk
三、其他查找
3.1 获取nginx版本号
问题描述:我们知道nginx可以通过-v/-V来获取版本信息,但如果直接将查询赋给变量就会发现不能成功,如下图所示。
处理办法:变量没有承接成功的原因是nginx将信息输出来了stderr而不是stdout,要承接我们需要将stderr重定向到stdout。
nginx_version=`nginx -v 2>&1`
参考:https://serverfault.com/questions/794873/cant-store-nginx-version-to-variable
3.2 获取tomcat版本号
问题描述:tomcat的版本号并不在响应的Server头中,只显示在默认的index.jsp和默认的错误页面中,此时可以通过curl获取其版本号(判断tomcat有没有设置隐藏版本号)。但如果默认index.jsp被删除且自定义了错误页面我们该如何通过shell获取到tomcat的版本号呢。
处理办法:此时我们还有三种办法可以获取到版本号。
第一种,解压$CATALINA_HOME/lib/catalina.jar,到org\apache\catalina\util\ServerInfo.properties文件中查看版本号。这理论上对服务没有影响,但动服务器文件的做法并不是很好。
第二种,使用java -cp $CATALINA_HOME/lib/catalina.jar org.apache.catalina.util.ServerInfo使用查看版本号。不过注意查找版本号的服务并不一定是运行tomcat的前户,其环境变量中并不一定有java。
第三种,运行$CATALINA_HOME/bin/version.sh获取版本信息。这个本质上还是执行第二种中的语句,一样需要有java命令才能获取结果。
参考:https://community.rsa.com/docs/DOC-81702
转载于//www.cnblogs.com/lsdb/p/10213076.html
还没有评论,来说两句吧...