Linux命令以及shell脚本

linux和shell的关系

shell的理解
shell翻译成壳的意思,它是包裹在linux内核外层的,一个可通过一系列的linux命令对操作系统发出相关指令的人机界面。 shell可以通过其条件语句和循环语句等,把一系列linux命令结合在一起,形成一个相当于面向过程的程序,shell script,来实现一些较为复杂的功能。

shell是linux命令集的概称,是属于命令行的人机界面。Shell 是一个用C语言编写的程序,它是用户使用Linux的桥梁。Shell既是一种命令语言,又是一种程序设计语言。Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。Ken Thompson的sh是第一种Unix Shell,Windows Explorer是一个典型的图形界面Shell。Shell 和Shell Script不是一回事,通常我们说的都是Shell Script。

由定义可知, shell相当于经过装饰的命令行,和命令行一样,都能操作linux。但是shell是面向过程的,相当于有了一定的逻辑和过程,而命令行只是单一的操作。

区别
1、直接在命令行执行 就是在当前的shell环境下执行 比如涉及到一些环境变量的时候 必须在当前shell环境里执行。在脚本里执行的话 脚本执行的时候 会fork一个子进程 所有操作都在子进程进行 如果涉及到一些在脚本里设置环境变量的东西 脚本结束了 环境变量也就消失了。
这个修改环境变量的话,需要特别注意下。

2、shell可以重复执行一些命令。你也可以把自己要重复执行的命令写到脚本里面执行。而命令行的话就需要一个一个的输入命令,相对而言麻烦一些。

一、shell脚本语法

https://blog.csdn.net/xhaimail/article/details/103208901

[ function ] funname [()]

{

    action;

    [return int;]

}

(一)可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。function关键字可以省略。

(二)在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数。注意: 10 不能获取第十个参数,获取第十个参数需要 10 不能获取第十个参数,获取第十个参数需要 10不能获取第十个参数,获取第十个参数需要{10}。当n>=10时,需要使用${n}来获取参数。

#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com

funWithParam(){
    echo "第一个参数为 $1 !"
    echo "第二个参数为 $2 !"
    echo "第十个参数为 $10 !"
    echo "第十个参数为 ${10} !"
    echo "第十一个参数为 ${11} !"
    echo "参数总数有 $# 个!"
    echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73

#输出结果:
#第一个参数为 1 !
#第二个参数为 2 !
#第十个参数为 10 !
#第十个参数为 34 !
#第十一个参数为 73 !
#参数总数有 11 个!
#作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !

(三)参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)
1.退出状态码
Shell 中运行的每个命令都使用退出状态码(exit status)来告诉shell它完成了处理。退出状态码是一个0-255之间的整数值,在命令结束运行时由命令传给shell。你可以捕获这个值并在脚本中使用。
Linux提供了 $? 专属变量来保存上个执行的命令的退出状态码。你必须在你要查看的命令之后马上查看或使用 $? 变量。它的值会变成Shell中执行的最后一条命令的退出状态码。

退出状态码大体分两种:
一种是命令正确执行的状态码,该状态码为:0
一种是命令错误执行的状态码,为1-255
Linux命令以及shell脚本_第1张图片
在脚本中也可以指定退出状态码的值,通过命令exit实现。

状态码取值范围为0-255,如果在指定的状态码大于255,那么shell会通过模(模就是256)运算得到相应的退出状态码。

2.函数返回值
1)return 语句
Shell函数的返回值,可以和其他语言的返回值一样,通过return语句返回,return只能用来返回整数值。

2)echo 语句
echo是通过输出到标准输出返回,可以返回任何类型的数据。

3.获取函数返回值
1)用 $? 获取返回状态
2)echo 语句获取

#!/bin/bash
 
#创建目录
function Compare(){
	if [ $1 != "string" ]; then
		echo "para is not string"
		
	else
        echo "para is string"
	fi
}

#方法一 
echo `Compare string`
#将函数的输出保存为变量
para=`Compare string`
echo ${para}

#方法二
echo $(Compare string) 
#将函数的输出保存为变量
para=$(Compare string) 
echo ${para}

方法一和方法二的原理一样的,将getStr当成命令执行,然后获取其标准输出。

(一)监控进程脚本

https://blog.csdn.net/s18754992795/article/details/113173721

#!/bin/sh
 
# 函数: CheckProcess
# 功能: 检查一个进程是否存在
# 参数: $1 --- 要检查的进程名称
# 返回: 如果存在返回0, 否则返回1.
#------------------------------------------------------------------------------
CheckProcess()
{
  # 检查输入的参数是否有效
  if [ "$1" = "" ];
  then
    return 1
  fi
 
  #$PROCESS_NUM获取指定进程名的数目,为1返回0,表示正常,不为1返回1,表示有错误,需要重新启动
  PROCESS_NUM=`ps -ef | grep "$1" | grep -v "grep" | wc -l` 
  if [ $PROCESS_NUM -eq 1 ];
  then
    return 0
  else
    return 1
  fi
}
 
 
# 检查test实例是否已经存在
while [ 1 ] ; do
     CheckProcess "test"
     Check_RET=$?
     if [ $Check_RET -eq 1 ];
     then
        echo "服务不正常"
        # 隐藏启动test 
         nohup ./test  > nohuptest.file 2>&1 &
    else
        echo "服务正常"
    fi
 sleep 60
done

二、Linux命令

(一)Linux Shell nohup命令用法

  nohup是Linux中的一个命令,用于在后台运行Shell脚本或命令,并让其在用户退出登录后继续运行。它的用法如下:

nohup command &

  其中,command 是要运行的Shell脚本或命令。& 符号让该命令在后台运行。nohup命令会把输出重定向到一个名为nohup.out的文件中,如果没有指定其他的输出文件。例如,要在后台运行一个名为myscript.sh的Shell脚本,并将输出重定向output.log文件中,可以使用以下命令:

nohup ./myscript.sh > output.log &

  在以上命令执行后,脚本将在后台运行,即使用户退出登录,脚本也会继续执行。同时,脚本的输出将被重定向到output.log文件中。值得注意的是,nohup命令会将标准输出和标准错误输出合并到同一个文件中。如果希望将它们分开保存到不同的文件中,可以使用重定向符号1>2>,例如:

nohup ./myscript.sh 1> stdout.log 2> stderr.log &

这样,标准输出将被重定向到stdout.log文件,标准错误输出将被重定向到stderr.log文件。

(二)如何理解Linux shell中的“2>&1”

具体例子参考:https://zhuanlan.zhihu.com/p/47765176

./test.sh  > log.txt 2>&1

结论:
上面的调用表明将./test.sh的输出1重定向到log.txt文件中,同时将标准错误2也重定向到log.txt文件中。
解析:
  每个程序在运行后,都会至少打开三个文件描述符,分别是0:标准输入:1:标准输出;2:标准错误。2>&1表明将文件描述2(标准错误输出)的内容重定向到文件描述符1(标准输出)。
  为什么1前面需要&?当没有&时,1会被认为是一个普通的文件(如果使用2>1,实际上是将标准错误输出重定向到一个名为1的文件)。有&表示重定向的目标不是一个文件,而是一个文件描述符。在前面我们知道,test.sh >log.txt又将文件描述符1的内容重定向到了文件log.txt,那么通过2>&1最终标准错误也会重定向到log.txt。
总结:
1.程序运行后会打开三个文件描述符,分别是标准输入0,标准输出1和标准错误输出2。
2.在调用脚本时,可使用2>&1来将标准错误输出重定向。
3.只需要查看脚本的错误时,可将标准输出重定向到文件,而标准错误会打印在控制台,便于查看。
4.通过>>log.txt会将重定向内容追加到log.txt文件末尾。
5.通过查看/proc/进程id/fd下的内容,可了解进程打开的文件描述符信息。

(三)ps命令详解

ps命令是pcrocess status的缩写,用于查看系统当前运行进程的状态。要对进程和进行检测和控制,需要了解当前进程的情况,也就需要ps命令。Linux上的进程有五种状态:运行态(R)、睡眠态(S)、不可中断睡眠态(D)、僵尸态(Z)和停止态(T)。
Linux命令以及shell脚本_第2张图片

(四)Linux下的ELF文件、链接、加载与库

https://blog.csdn.net/weixin_44966641/article/details/120631079

(一)ELF是一类文件类型,而不是特指某一后缀的文件。ELF(Executable and Linkable Format,可执行与可链接格式)文件格式,在Linux下主要有如下三种文件:

1.可执行文件(.out):Executable File,包含代码和数据,是可以直接运行的程序。其代码和数据都有固定的地址 (或相对于基地址的偏移 ),系统可根据这些地址信息把程序加载到内存执行。

2.可重定位文件(.o文件):Relocatable File,包含基础代码和数据,但它的代码及数据都没有指定绝对地址,因此它适合于与其他目标文件链接来创建可执行文件或者共享目标文件。

3.共享目标文件(.so):Shared Object File,也称动态库文件,包含了代码和数据,这些数据是在链接时被链接器(ld)和运行时动态链接器(ld.so.l、libc.so.l、ld-linux.so.l)使用的。

(二)ELF文件的结构
Linux命令以及shell脚本_第3张图片
ELF文件由4部分组成,分别是ELF头(ELF header)、程序头表(Program header table)、节(Section)和节头表(Section header table)。实际上,一个文件中不一定包含全部内容,而且它们的位置也未必如同所示这样安排,只有ELF头的位置是固定的,其余各部分的位置、大小等信息由ELF头中的各项值来决定。

(三)链接是将将各种代码和数据片段收集并组合为一个单一文件的过程,这个文件可以被加载到内存并执行。链接可以执行与编译时,也就是在源代码被翻译成机器代码时;也可以执行于加载时,也就是被加载器加载到内存执行时;甚至执行于运行时,也就是由应用程序来执行。

三、Linux环境变量

(一)Linux中PATH、 LIBRARY_PATH、 LD_LIBRARY_PATH的区别

https://blog.csdn.net/weixin_48859611/article/details/113986310

1. PATH

PATH是可执行文件路径 命令行中的命令,如ls等等,都是系统通过PATH找到了这个命令执行文件的所在位置,再run这个命令(可执行文件)。

所以,PATH 配置的路径下的文件可以在任何位置执行,并且可以通过which 可执行文件 命令来找到该文件的位置

2. LIBRARY_PATH

LIBRARY_PATH是在程序编译期间查找动态链接库时指定的查找共享库的路径。

3. LD_LIBRARY_PATH

主要是用于指定动态链接器(ld)查找ELF可执行文件运行时所依赖的动态库(so)的路径。即用于在程序运行期间查找动态链接库时,指定除了系统默认路径(/usr/lib)之外的路径.

(二)解决运行时找不到动态链接库的问题

程序可以顺利编译但是无法运行,提示找不到动态链接库。直接将缺失的库放在/usr/lib下程序可正常执行。尝试不改变/usr/lib中的内容,使用改变系统环境变量的方法解决该问题
为什么修改LD_LIBRARY_PATH呢
因为运行时动态库的搜索路径的先后顺序是:
1.编译目标代码时指定的动态库搜索路径;
2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
3.配置文件/etc/ld.so.conf中指定的动态库搜索路径;
4.默认的动态库搜索路径/lib和/usr/lib;

参考内容:https://blog.csdn.net/yueyecheshou1980/article/details/106096013?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-106096013-blog-125582219.235%5Ev38%5Epc_relevant_default_base&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-106096013-blog-125582219.235%5Ev38%5Epc_relevant_default_base&utm_relevant_index=2

解决方法:

1.修改LD_LIBRARY_PATH环境变量
1.通过命令临时改变变量
2.通过修改文件永久改变用户或者整个系统的变量

参考内容
https://blog.csdn.net/weixin_48859611/article/details/113986310
https://blog.csdn.net/xishining/article/details/119283522

可以通过在**/etc/ld.so.conf.d路径下增加.conf**文件,在文件中增加需要搜索的动态库路径后。在终端输入ldconfig命令后系统就会搜索.conf文件中的路径。

2.cmake分别指定编译/运行时动态库链接路径(待验证)

可以通过在CmakeLists中制定运行时的动态链接库路径,方便程序移植。

https://blog.csdn.net/JCYAO_/article/details/102519998

你可能感兴趣的:(开发语言)