命令执行顺序以及进程列表

文章目录

  • 1. “&&”规则执行命令
    • 1.2 命令1 && 命令2
  • 2. “||”规则执行命令
    • 2.1 命令1 || 命令2
  • 3. 进程列表
    • 3.1 圆括号方式产生子shell进程
    • 3.2 花括号方式不产生子shell进程
  • 4. 进程列表()、{}搭配&&、||一起使用

1. “&&”规则执行命令

     一般情况下, 成果物只有一个(各模块). 因此开启服务只需简单的 ./成果物名字; 但是很多情况下, 我们都会为自身的模块服务提供一个看门狗进程, 即当服务出现意外而挂掉时候, 希望看门狗进程能够立即将服务拉起来, 而不是让服务处于瘫痪状态. 这时候服务启动时候, 则涉及两个进程. 而且这两个进程的顺序是:

     看门狗进程启动ok, 则继续启动模块进程服务; 反之, 则启动服务失败. 如下图所示:
命令执行顺序以及进程列表_第1张图片
     如下示例1, 分别有两个进程hello(打印helo . . . )和world(打印world . . .).

///// hello.c文件内容  gcc hello.c -o hello   (进程名hello)
#include 
#include 
int main()
{
        printf("hello ...\n");
        return 0;
}

///// world.c文件内容  gcc world.c -o world  (进程名world)
#include 
#include 
int main()
{
        printf("world ...\n");
        return 0;
}

     若不使用“&&”, 那么其shell脚本应该如下. 若hello进程启动成功, 则继续启动world进程, 反之, 则结束.

#!/bin/sh
./hello
if [ $? -eq 0 ]
then
    ./world
fi

1.2 命令1 && 命令2

     现在修改为使用“&&”命令来替换if. . . else规则. 如下:

#!/bin/sh
# 如果./hello命令启动成功(返回真, 即$? = 0), 则继续启动 ./world进程; 若失败, 则结束.
./hello && ./world   

     为了测试“&&”的使用规则, 现在启动一个不存在的进程hello_1. 观察其结果:

#!/bin/sh
./hello_1 && ./world

     因为不存在hello_1进程, 因此直接报错, hello和world都没有启动和打印. 报错提示如下:
     start.sh: line 2: ./hello_1: No such file or directory

2. “||”规则执行命令

2.1 命令1 || 命令2

     对于Shell环境中“||”命令的功能. 若命令1执行失败, 不会退出, 转而执行命令2. 若命令1执行成功, 则不会执行命令2.

     先来一个命令1执行成功的示例.

///// start.sh 脚本
#!/bin/sh
./hello || ./world

     打印结果:
     hello . . .

     现在修改start.sh脚本. 其中命令1不存在, 然后执行:

///// start.sh 脚本
#!/bin/sh
# hello_1成果物是不存在的. 所以hello_1执行失败. 观察world执行情况.
./hello_1 || ./world

     打印结果:
     start.sh: line 2: ./hello_1: No such file or directory
     world . . .

     命令1执行失败并报错. 但并不影响脚本的继续执行. world进程仍然执行并打印数据了.

3. 进程列表

     对于shell, 可以在一行中指定要依次执行的一系列命令. 各命令之间用分号(";")隔开; 这些命令依次执行.如下示例:

lixiaogang5@Cpl-Backend-General-14-115:~/work/test/06_29$ ls
1.sh  hello  hello.c  start.sh  world  world.c

# 使用pwd;ls两个组合命令来查看当前位置和文件列表.
lixiaogang5@Cpl-Backend-General-14-115:~/work/test/06_29$ pwd;ls
/data1/lixiaogang5/work/test/06_29
1.sh  hello  hello.c  start.sh  world  world.c

     所谓进程列表, 即命令分组. 若只是简单的将一个或多个命令使用分号隔开写在一行中, 并不会成为进程列表. 想要成为进程列表, 有两种方式, 分别是: 使用圆括号() 或 使用花括号{}来将命令放入其中. 并在每个命令的末尾加上分号(";"). 语法格式如下:
     {commond 1; commond 2; commond 3}    /*使用花括号方式*/
     (commond 1; commond 2; commond 3})   /*使用圆括号方式*/

     尽管使用圆括号和花括号方式都可以达到进程列表的目的与效果. 但是两者是有区别的. 圆括号方式会生成一个子shell来执行对应的命令; 而使用花括号方式进行命令分组时候, 并不创建子shell.

3.1 圆括号方式产生子shell进程

     为了验证是否生产子shell, 可以使用环境变量 BASH_SUBSHELL. 若返回0, 则表示没有创建子shell; 反之, 若返回1或是其他数字, 则表示创建了子shell进程.

lixiaogang5@Cpl-Backend-General-14-115:~/work/test/06_29$ (pwd; ls; echo $BASH_SUBSHELL)
/data1/lixiaogang5/work/test/06_29
1.sh  hello  hello.c  start.sh  world  world.c
1  //echo $BASH_SUBSHELL 返回结果大于0, 表示创建了子shell进程环境.

3.2 花括号方式不产生子shell进程

     使用花括号方式来创建进程列表, 如下:

lixiaogang5@Cpl-Backend-General-14-115:~/work/test/06_29$ {pwd; ls; echo $BASH_SUBSHELL}
/data1/lixiaogang5/work/test/06_29
1.sh  hello  hello.c  start.sh  world  world.c
0  //使用花括号方式, echo $BASH_SUBSHELL 返回结果为0, 表示没有创建子shell.

     圆括号或花括号创建进程列表时候, 内部还可以嵌套圆括号或花括号. 如下:

lixiaogang5@Cpl-Backend-General-14-115:~/work/test/06_29$ (pwd; ls; (echo $BASH_SUBSHELL))
/data1/lixiaogang5/work/test/06_29
1.sh  hello  hello.c  start.sh  world  world.c
2   //这个时候环境变量BASH_SUBSHELL为2, 表示创建了2个子shell环境》 

4. 进程列表()、{}搭配&&、||一起使用

     很多时候, 对于一些比较耗时的操作, 可以另起一个子shell环境并在其中去执行. 模拟多进程的场景效果. 如下所示:

lixiaogang5@Cpl-Backend-General-14-115:~/work/test/06_29$ ./hello && ./world || (echo "execute failed.")
hello ...
world ...

# 执行失败范例
lixiaogang5@Cpl-Backend-General-14-115:~/work/test/06_29$ ./hello_1 && ./world || (echo "execute failed.")
bash: ./hello_1: No such file or directory
execute failed.

你可能感兴趣的:(shell)