【原创】Linux 下程序后台运行相关问题总结

千言万语,不如实验来的直接... 

基于sleep的小实验

      首先通过实验直观感受一下后台服务的运行状况(请注意,前方高能,相关概念在更后面才有解释)。 

在命令行上以不同方式执行 sleep

确定登录 shell 和伪终端。 

?


1

2

3

4

5

6

7

8

9

10

11

12

[root@YOYO ~]# ps ajxf         

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND

...

    0     1     1     1 ?           -1 Ss       0   0:02 /sbin/init

...

    1  1654  1654  1654 ?           -1 Ss       0   0:00 /usr/sbin/sshd

 1654 15437 15437 15437 ?           -1 Ss       0   0:00  \_ sshd: root@pts/0,pts/1

15437 15441 15441 15441 pts/0    15441 Ss+      0   0:00      \_ -bash

15437 16237 16237 16237 pts/1    16258 Ss       0   0:00      \_ -bash

16237 16258 16258 16237 pts/1    16258 R+       0   0:00          \_ ps ajxf

...

[root@YOYO ~]#

分别以后台方式(&)、setsid、nohup 和前台方式执行 sleep  

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

[root@YOYO ~]# jobs -l         

[root@YOYO ~]#

[root@YOYO ~]# sleep 600 &        -- 通过 & 后台运行   -- 1

[1] 16261

[root@YOYO ~]#

[root@YOYO ~]# setsid sleep 660   -- 通过 setsid 后台运行   -- 2

[root@YOYO ~]#

[root@YOYO ~]# nohup sleep 720 &   -- 通过 nohup + & 后台运行   -- 3

[2] 16271

[root@YOYO ~]# nohup: 忽略输入并把输出追加到"nohup.out"

 

[root@YOYO ~]#

[root@YOYO ~]# sleep 780        -- 前台运行   -- 4

^Z                              -- 挂起

[3]+  Stopped                 sleep 780

[root@YOYO ~]#

[root@YOYO ~]# jobs -l

[1]  16261 Running                 sleep 600 &

[2]- 16271 Running                 nohup sleep 720 &

[3]+ 16274 停止                  sleep 780

[root@YOYO ~]#

[root@YOYO ~]# bg 3             -- 放入后台运行

[3]+ sleep 780 &

[root@YOYO ~]#

[root@YOYO ~]# jobs -l

[1]  16261 Running                 sleep 600 &

[2]- 16271 Running                 nohup sleep 720 &

[3]+ 16274 Running                 sleep 780 &

[root@YOYO ~]#

查看此时的进程关系 

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

[root@YOYO ~]# ps ajxf         

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND

...

    0     1     1     1 ?           -1 Ss       0   0:02 /sbin/init

...

    1  1654  1654  1654 ?           -1 Ss       0   0:00 /usr/sbin/sshd

 1654 15437 15437 15437 ?           -1 Ss       0   0:00  \_ sshd: root@pts/0,pts/1

15437 15441 15441 15441 pts/0    15441 Ss+      0   0:00      \_ -bash

15437 16237 16237 16237 pts/1    16282 Ss       0   0:00      \_ -bash

16237 16261 16261 16237 pts/1    16282 S        0   0:00          \_ sleep 600       -- 1

16237 16271 16271 16237 pts/1    16282 S        0   0:00          \_ sleep 720       -- 3

16237 16274 16274 16237 pts/1    16282 S        0   0:00          \_ sleep 780       -- 4

16237 16282 16282 16237 pts/1    16282 R+       0   0:00          \_ ps ajxf

...

    1 16265 16265 16265 ?           -1 Ss       0   0:00 sleep 660         -- 2

[root@YOYO ~]#

叉掉 ssh 连接窗口,查看此时的 sleep 进程状态 

?


1

2

3

4

5

6

7

8

9

10

11

12

13

[root@YOYO ~]# ps ajxf

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND

...

    0     1     1     1 ?           -1 Ss       0   0:02 /sbin/init

...

    1  1654  1654  1654 ?           -1 Ss       0   0:00 /usr/sbin/sshd

 1654 15437 15437 15437 ?           -1 Ss       0   0:00  \_ sshd: root@pts/0

15437 15441 15441 15441 pts/0    16300 Ss       0   0:00      \_ -bash

15441 16300 16300 15441 pts/0    16300 R+       0   0:00          \_ ps ajxf

...

    1 16265 16265 16265 ?           -1 Ss       0   0:00 sleep 660      -- 2

    1 16271 16271 16237 ?           -1 S        0   0:00 sleep 720      -- 3

[root@YOYO ~]#

实验结论: 
以不同方式启动进程,在 ssh 连接窗口被叉掉的时候会造成不同的影响。标号为 1 和 4 的两个进程都消失了,标号为 3 的进程有属性发生了变化,只有标号为 2 的进程没有任何改变。 

在 shell 脚本中上以不同方式执行 sleep

测试一(前台进程组) 

?


1

2

3

4

5

6

7

8

[root@Betty ~]# vi test_1.sh

  

#!/bin/sh

sleep 600        # 会卡住当前 shell 脚本

  

[root@Betty ~]#

[root@Betty ~]# ./test_1.sh

(卡住)

 在另一个窗口中查看 

?


1

2

3

4

5

6

7

8

9

10

[root@Betty ~]# ps ajxf

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND

...

    1  1860  1860  1860 ?           -1 Ss       0   0:00 /usr/sbin/sshd

 1860 13331 13331 13331 ?           -1 Ss       0   0:00  \_ sshd: root@pts/1,pts/2

13331 16993 16993 16993 pts/1    18649 Ss       0   0:00      \_ -bash

16993 18649 18649 16993 pts/1    18649 R+       0   0:00      |   \_ ps ajxf

13331 18572 18572 18572 pts/2    18632 Ss       0   0:00      \_ -bash

18572 18632 18632 18572 pts/2    18632 S+       0   0:00          \_ /bin/sh ./test_1.sh

18632 18633 18632 18572 pts/2    18632 S+       0   0:00              \_ sleep 600

此时叉掉启动 test_1.sh 脚本的窗口,可以看到对应的进程全部消失。 

?


1

2

3

4

5

6

7

[root@Betty ~]# ps ajxf

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND

...

    1  1860  1860  1860 ?           -1 Ss       0   0:00 /usr/sbin/sshd

 1860 13331 13331 13331 ?           -1 Ss       0   0:00  \_ sshd: root@pts/1

13331 16993 16993 16993 pts/1    18706 Ss       0   0:00      \_ -bash

16993 18706 18706 16993 pts/1    18706 R+       0   0:00          \_ ps ajxf

测试二(孤儿后台进程组) 

?


1

2

3

4

5

6

7

8

[root@Betty ~]# vi test_2.sh

  

#!/bin/sh

sleep 600 &         # 不会卡住当前 shell 脚本,因为放在后台执行

   

[root@Betty ~]#

[root@Betty ~]# ./test_2.sh

[root@Betty ~]#

在另一个窗口中查看 

?


1

2

3

4

5

6

7

8

9

10

11

12

13

[root@Betty ~]# ps ajxf

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND

...

    1  1860  1860  1860 ?           -1 Ss       0   0:00 /usr/sbin/sshd

 1860 13331 13331 13331 ?           -1 Ss       0   0:00  \_ sshd: root@pts/1,pts/0

13331 16993 16993 16993 pts/1    18778 Ss       0   0:00      \_ -bash

16993 18778 18778 16993 pts/1    18778 R+       0   0:00      |   \_ ps ajxf

13331 18734 18734 18734 pts/0    18734 Ss+      0   0:00      \_ -bash

...

1 18763 18762 18734 pts/0    18734 S        0   0:00 sleep 600  -- 对应后台执行 sleep 的进程,由于是后台执行,

                                                                   所以不会卡住 test.sh 脚本的执行

                                                                   test.sh 脚本执行结束后,与 test.sh 对应的进程

                                                                   会自行退出,从而 sleep 进程被 init 进程收养

此时叉掉启动 test_2.sh 脚本的窗口,可以看到 sleep 600 对应进程的 TTY 和 TPGID 发生了变化,但进程并未消失。 

?


1

2

3

4

5

6

7

8

9

[root@Betty ~]# ps ajxf

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND

...

    1  1860  1860  1860 ?           -1 Ss       0   0:00 /usr/sbin/sshd

 1860 13331 13331 13331 ?           -1 Ss       0   0:00  \_ sshd: root@pts/1

13331 16993 16993 16993 pts/1    18816 Ss       0   0:00      \_ -bash

16993 18816 18816 16993 pts/1    18816 R+       0   0:00          \_ ps ajxf

...

    1 18763 18762 18734 ?           -1 S        0   0:00 sleep 600

测试三(前台进程组) 

?


1

2

3

4

5

6

7

8

9

[root@Betty ~]# vi test_3.sh

  

#!/bin/sh

sleep 600 &

sleep 720

  

[root@Betty ~]#

[root@Betty ~]# ./test_3.sh

(卡住)

在另一个窗口中查看 

?


1

2

3

4

5

6

7

8

9

10

11

12

13

[root@Betty ~]# ps ajxf

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND

...

    1  1860  1860  1860 ?           -1 Ss       0   0:00 /usr/sbin/sshd

 1860 13331 13331 13331 ?           -1 Ss       0   0:00  \_ sshd: root@pts/1,pts/2

13331 16993 16993 16993 pts/1    18918 Ss       0   0:00      \_ -bash

16993 18918 18918 16993 pts/1    18918 R+       0   0:00      |   \_ ps ajxf

13331 18856 18856 18856 pts/2    18908 Ss       0   0:00      \_ -bash

18856 18908 18908 18856 pts/2    18908 S+       0   0:00          \_ /bin/sh ./test_3.sh

18908 18909 18908 18856 pts/2    18908 S+       0   0:00              \_ sleep 600

18908 18910 18908 18856 pts/2    18908 S+       0   0:00              \_ sleep 720

...

[root@Betty ~]#

 此时叉掉启动 test_3.sh 脚本的窗口,可以看到对应的进程全部消失。  

?


1

2

3

4

5

6

7

8

9

[root@Betty ~]# ps ajxf

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND

...

    1  1860  1860  1860 ?           -1 Ss       0   0:00 /usr/sbin/sshd

 1860 13331 13331 13331 ?           -1 Ss       0   0:00  \_ sshd: root@pts/1

13331 16993 16993 16993 pts/1    18963 Ss       0   0:00      \_ -bash

16993 18963 18963 16993 pts/1    18963 R+       0   0:00          \_ ps ajxf

...

[root@Betty ~]#

测试四(后台进程组) 

?


1

2

3

4

5

6

7

8

9

10

[root@Betty ~]# cat test_1.sh

 

#!/bin/sh

sleep 600

  

[root@Betty ~]#

[root@Betty ~]#

[root@Betty ~]# ./test_1.sh &   -- 后台执行该脚本

[1] 19016

[root@Betty ~]#

 在另外一个窗口中查看 

?


1

2

3

4

5

6

7

8

9

10

11

12

[root@Betty ~]# ps ajxf

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND

...

    1  1860  1860  1860 ?           -1 Ss       0   0:00 /usr/sbin/sshd

 1860 13331 13331 13331 ?           -1 Ss       0   0:00  \_ sshd: root@pts/1,pts/0

13331 16993 16993 16993 pts/1    19032 Ss       0   0:00      \_ -bash

16993 19032 19032 16993 pts/1    19032 R+       0   0:00      |   \_ ps ajxf

13331 18993 18993 18993 pts/0    18993 Ss+      0   0:00      \_ -bash

18993 19016 19016 18993 pts/0    18993 S        0   0:00          \_ /bin/sh ./test_1.sh

19016 19017 19016 18993 pts/0    18993 S        0   0:00              \_ sleep 600

...

[root@Betty ~]#

此时叉掉后台启动 test_1.sh 脚本的窗口,可以看到对应的进程全部消失。 

?


1

2

3

4

5

6

7

8

9

[root@Betty ~]# ps ajxf

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND

...

    1  1860  1860  1860 ?           -1 Ss       0   0:00 /usr/sbin/sshd

 1860 13331 13331 13331 ?           -1 Ss       0   0:00  \_ sshd: root@pts/1

13331 16993 16993 16993 pts/1    19052 Ss       0   0:00      \_ -bash

16993 19052 19052 16993 pts/1    19052 R+       0   0:00          \_ ps ajxf

...

[root@Betty ~]#

实验结论: 

  • 如果 shell 脚本中存在前台执行的命令,则在其未执行结束前,会“卡住”当前 shell 脚本对应的进程,进而“卡住”bash 进程。即整个进程树在 ps ajxf 中都会作为前台进程组显示。
  • & 的使用在 shell 脚本内外会产生不同的效果,在 shell 脚本内可以产生孤儿进程组(前提是没有其他命令的执行导致 shell 脚本无法退出),在脚本外则产生普通的后台进程组;
  • 对于孤儿进程组和普通后台进程组 SIGHUP 信号在处理细节上是不同的;

相关概念

要想理解上面的实验结果,首先必须理解如下一些概念:

【进程组】 

  • 一个或多个进程的集合。通常与同一作业(job)相关联。
  • 每个进程组都可以有一个组长进程,组长进程的特征是“进程组 ID 等于其进程 ID”,即PGID = PID。
  • 组长进程自身可以在创建一个进程组后,再创建该进程组中的其他进程,然后终止自己。
  • 只要在某个进程组中有一个进程存在,则该进程组就存在,这与其组长进程是否终止无关。
  • 进程可以通过调用 setpgid 来加入一个现有的进程组或者创建一个新进程组(也可以通过 setsid 创建一个新的进程组)。
  • 一个进程只能为它自己或它的子进程设置进程组 ID。


【会话】
 

  • POSIX.1 引入会话(session)的概念。
  • 登录 shell 是一个会话的开始,而终端或伪终端则是会话的控制终端。
  • 会话是一个或多个进程组的集合。
  • 进程通过调用 setsid 函数建立一个新会话。
  • 如果调用 setsid 函数的进程不是一个进程组的组长,则调用 setsid 函数就会创建一个新会话,同时发生下面 3 件事,
    (a) 该进程变成会话首进程(session leader)(会话首进程是创建该会话的进程);
    (b) 该进程成为一个新进程组的组长进程。新进程组 ID 是该调用进程的进程 ID;
    (c) 该进程没有控制终端,如果在调用 setsid 之前,该进程有一个控制终端,那么这种联系也会被中断。
  • 如果调用此函数的进程已经是一个进程组的组长,则此函数返回出错。为了保证不会发生这种情况,通常先调用 fork,然后使其父进程终止,而子进程则继续。因为子进程继承了父进程的进程组 ID,而其进程 ID 则是新分配的,两者不可能相等,所以就保证了子进程不会是一个进程组的组长。
  • 会话首进程总是一个进程组的组长进程,所以两者是等价的。所以可以认为
    会话首进程ID = 会话ID = 进程组ID = 进程组组长ID 
  • 一个会话中包含的多个进程组可以被分成一个前台进程组(foreground process group)以及一个或几个后台进程组(background process group)。


【登陆shell】
 
当通过终端或网络登录时,可以得到一个登录 shell,其标准输入、输出和标准出错将连接到一个终端设备或者伪终端设备上。 

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

[root@Betty ~]# ps ajxf

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND

...

    1  1860  1860  1860 ?           -1 Ss       0   0:00 /usr/sbin/sshd

 1860  2228  2228  2228 ?           -1 Ss       0   0:02  \_ sshd: root@pts/1,pts/2,pts/3,pts/4,pts/0,pts/5,pts/6,pts/7,pts/8,pts/9

 2228  2230  2230  2230 pts/1     2230 Ss+      0   0:00      \_ -bash

 2228  2747  2747  2747 pts/2     2747 Ss+      0   0:00      \_ -bash

 2228  2772  2772  2772 pts/3     2772 Ss+      0   0:00      \_ -bash

 2228  6750  6750  6750 pts/4    16910 Ss       0   0:00      \_ -bash

 6750 16910 16910  6750 pts/4    16910 Sl+      0   0:02      |   \_ ./modb /etc/modbcore.conf

 2228  7213  7213  7213 pts/0     7213 Ss+      0   0:00      \_ -bash

 2228 17072 17072 17072 pts/5    17072 Ss+      0   0:00      \_ -bash

 2228 17091 17091 17091 pts/6    17091 Ss+      0   0:00      \_ -bash

 2228 17111 17111 17111 pts/7    17111 Ss+      0   0:00      \_ -bash

 2228 17132 17132 17132 pts/8    17132 Ss+      0   0:00      \_ -bash

 2228 17154 17154 17154 pts/9    17175 Ss       0   0:00      \_ -bash

17154 17175 17175 17154 pts/9    17175 R+       0   0:00          \_ ps ajxf

      可以看到,上面所有 -bash 均为通过 ssh 网络连接建立的登陆 shell,且都对应到 pts 伪终端上,即登陆 shell 拥有控制终端。 
      另外,可以看到登陆 shell 的 PID = PGID = SID,所以登陆 shell 就是会话首进程,以及进程组组长进程。 
      登陆 shell 是一个 POSIX.1 会话的开始,而此终端或伪终端则是会话的控制终端。

【伪终端】 
      为使同一个软件既能处理终端 login,又能处理网络 login,系统使用了一种称为伪终端的软件驱动程序,它仿真串行终端的运行行为,并将终端操作映射为网络操作,反之亦然。 
      当通过终端(基于硬链接和终端设备驱动程序)或网络(基于网络连接和伪终端设备驱动程序)登录时,我们得到一个登录 shell,其标准输入、输出和标准出错连接到一个终端设备或者伪终端设备上。 

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

[root@YOYO ~]# w

 14:58:20 up 2 days,  5:30,  1 user,  load average: 0.00, 0.00, 0.00

USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT

root     pts/1    172.16.81.112    Mon09    0.00s  0.45s  0.07s w

[root@YOYO ~]#

[root@YOYO ~]#

[root@YOYO ~]# ps aux|grep bash

root      2030  0.0  0.0 108552  2000 pts/1    Ss   Jul13   0:00 -bash

root     24962  0.0  0.0 103256   856 pts/1    S+   14:58   0:00 grep bash

[root@YOYO ~]# ll /proc/2030/fd

总用量 0

lrwx------. 1 root root 64 7月  13 09:43 0 -> /dev/pts/1

lrwx------. 1 root root 64 7月  13 09:43 1 -> /dev/pts/1

lrwx------. 1 root root 64 7月  13 09:43 2 -> /dev/pts/1

lrwx------. 1 root root 64 7月  15 11:04 255 -> /dev/pts/1

[root@YOYO ~]#


【控制终端】
 

  • 一个会话可以有一个控制终端(controlling terminal),这通常是登陆到其上的终端设备(终端登陆)或伪终端设备(网络登录)。
  • 只有建立与控制终端连接的会话首进程被称为控制进程(controlling process)。
  • 如果一个会话有一个控制终端,则它有一个前台进程组,会话中的其他进程组则为后台进程组。
  • 无论何时键入终端的中断键(Ctrl+C),就会将中断信号 SIGINT 发送给前台进程组中的所有进程;
  • 无论何时键入终端的退出键(Ctrl+\),就会将退出信号 SIGQUIT 发送给前台进程组中的所有进程;
  • 如果终端接口检测到调制解调器或网路已经断开连接,则将挂断信号 SIGHUP 发送给控制进程(会话首进程)。
  • 如果在调用setsid之前某进程有一个控制终端,那么在调用后该控制终端会被中断。


【作业控制】
 
作业控制是 BSD 在 1980 年前后增加的一个特性。它允许在一个终端上启动多个作业(进程组),它控制哪一个作业可以访问该终端,以及哪些作业在后台运行。 

【信号】 

  • SIGTTOU - 后台作业试图输出到控制终端,若用户设置了禁止后台作业写到控制终端(stty tostop),终端驱动程序会将该写操作标识为来自于后台进程,会向其发送该信号。
  • SIGTTIN - 后台作业试图读取控制终端,终端驱动程序发现后,会向后台作业发送该信号。
  • SIGTSTP - 键入Ctrl+Z挂起键与终端驱动程序进行交互,令其将该信号送至前台进程组中的所有进程,后台进程组作业不受影响。
  • SIGHUP - 当检测到来自控制终端的 Hangup 信号时,或者当控制进程死亡时 (signal(7))

【守护进程】 

  • 守护进程也称为 daemon,是生存期较长的一种进程。常常在系统自举时启动,仅在系统关闭时才终止。没有控制终端,在后台运行。
  • 大多数守护进程都以超级用户(UID 为 0)特权运行。
  • 守护进程没有控制终端,ps 输出时,其控制终端显示为问号(?),前台进程组 ID 为 -1。
  • 内核守护进程一般会以无控制终端方式启动;而用户实现的守护进程若没有控制终端,则可能是因为创建守护进程时调用了 setsid。
  • 大多数守护进程的父进程是 init 进程。

【孤儿进程组】 

  • 一个其父进程已经终止的进程称为孤儿进程,这种进程会被 init 进程“收养”;
  • POSIX.1 将孤儿进程组定义为:该进程组中每个成员的父进程要么是该组的一个成员,要么不是该组所属会话的成员;
  • 对孤儿进程组的另一种描述为:一个进程组不是孤儿进程组的条件是,该组中有一个进程,其父进程在属于同一会话的另一个组中。
  • 若父进程退出导致进程组成为孤儿进程组,且该进程组中有进程处于停止状态(收到 SIGSTOP 或 SIGTSTP 信号后被挂起),信号 SIGHUP 会被发送到该进程组中的每一个被挂起的进程。

进程消失的原因--SIGHUP

之前整理了一篇关于 SIGHUP 信号的博文,下面 给出一些结论: 

  • 系统对 SIGHUP 信号的默认处理是终止收到该信号的进程。所以若程序中没有捕捉该信号,当收到该信号时,进程就会退出;
  • 终端(或伪终端)被关闭时,信号 SIGHUP 会被内核发送到具有控制终端的会话的会话首进程;
  • 会话首进程退出前,信号 SIGHUP 会被内核发送到当前会话中的前台进程组中的每一个进程;
  • bash 收到 SIGHUP 时,会给其下运行的各个作业(包括前后台)发送 SIGHUP,然后自己退出;
  • 前后台的各个作业收到来自 bash 的 SIGHUP 后将退出(如果存在针对 SIGHUP 的处理,就不会退出)

基于strace研究各种运行方式的差别

      既然知道了进程消失是因为 SIGHUP 信号导致,那么就可以通过 strace 观察各种运行方式下,都做了哪些相关处理。 

跟踪前台运行,可以看到其中没有针对 SIGHUP 信号做任何处理。 

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

[root@YOYO ~]# strace sleep 10

execve("/bin/sleep", ["sleep", "10"], [/* 28 vars */]) = 0

brk(0)                                  = 0xafa000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe54ec09000

access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)

open("/etc/ld.so.cache", O_RDONLY)      = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=70566, ...}) = 0

mmap(NULL, 70566, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe54ebf7000

close(3)                                = 0

open("/lib64/libc.so.6", O_RDONLY)      = 3

read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\356\0018?\0\0\0"..., 832) = 832

fstat(3, {st_mode=S_IFREG|0755, st_size=1926760, ...}) = 0

mmap(0x3f38000000, 3750152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3f38000000

mprotect(0x3f3818a000, 2097152, PROT_NONE) = 0

mmap(0x3f3838a000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18a000) = 0x3f3838a000

mmap(0x3f3838f000, 18696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3f3838f000

close(3)                                = 0

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe54ebf6000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe54ebf5000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe54ebf4000

arch_prctl(ARCH_SET_FS, 0x7fe54ebf5700) = 0

mprotect(0x3f3838a000, 16384, PROT_READ) = 0

mprotect(0x3f37a1f000, 4096, PROT_READ) = 0

munmap(0x7fe54ebf7000, 70566)           = 0

brk(0)                                  = 0xafa000

brk(0xb1b000)                           = 0xb1b000

open("/usr/lib/locale/locale-archive", O_RDONLY) = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=99154480, ...}) = 0

mmap(NULL, 99154480, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe548d64000

close(3)                                = 0

nanosleep({10, 0}, NULL)                = 0                -- 对应 sleep 10

close(1)                                = 0

close(2)                                = 0

exit_group(0)                           = ?

[root@YOYO ~]#

跟踪后台运行,可以看到其中同样没有针对SIGHUP信号做任何处理。 

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

[root@YOYO ~]# strace sleep 10 &

[1] 2727

[root@YOYO ~]# execve("/bin/sleep", ["sleep", "10"], [/* 28 vars */]) = 0

brk(0)                                  = 0x1406000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff18790f000

access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)

open("/etc/ld.so.cache", O_RDONLY)      = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=70566, ...}) = 0

mmap(NULL, 70566, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff1878fd000

close(3)                                = 0

open("/lib64/libc.so.6", O_RDONLY)      = 3

read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\356\0018?\0\0\0"..., 832) = 832

fstat(3, {st_mode=S_IFREG|0755, st_size=1926760, ...}) = 0

mmap(0x3f38000000, 3750152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3f38000000

mprotect(0x3f3818a000, 2097152, PROT_NONE) = 0

mmap(0x3f3838a000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18a000) = 0x3f3838a000

mmap(0x3f3838f000, 18696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3f3838f000

close(3)                                = 0

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff1878fc000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff1878fb000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff1878fa000

arch_prctl(ARCH_SET_FS, 0x7ff1878fb700) = 0

mprotect(0x3f3838a000, 16384, PROT_READ) = 0

mprotect(0x3f37a1f000, 4096, PROT_READ) = 0

munmap(0x7ff1878fd000, 70566)           = 0

brk(0)                                  = 0x1406000

brk(0x1427000)                          = 0x1427000

open("/usr/lib/locale/locale-archive", O_RDONLY) = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=99154480, ...}) = 0

mmap(NULL, 99154480, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff181a6a000

close(3)                                = 0

nanosleep({10, 0}, NULL)                = 0              -- 对应 sleep 10

close(1)                                = 0

close(2)                                = 0

exit_group(0)                           = ?

 

[1]+  Done                    strace sleep 10

[root@YOYO ~]#

跟踪 setsid 的使用,可以看到其中同样没有针对 SIGHUP 信号做任何处理(通过 setsid 执行后不会退出的原因后续再说明)。 

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

[root@YOYO ~]# strace setsid sleep 10       

execve("/usr/bin/setsid", ["setsid", "sleep", "10"], [/* 28 vars */]) = 0

brk(0)                                  = 0x1274000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2dc78d4000

access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)

open("/etc/ld.so.cache", O_RDONLY)      = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=70566, ...}) = 0

mmap(NULL, 70566, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f2dc78c2000

close(3)                                = 0

open("/lib64/libc.so.6", O_RDONLY)      = 3

read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\356\0018?\0\0\0"..., 832) = 832

fstat(3, {st_mode=S_IFREG|0755, st_size=1926760, ...}) = 0

mmap(0x3f38000000, 3750152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3f38000000

mprotect(0x3f3818a000, 2097152, PROT_NONE) = 0

mmap(0x3f3838a000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18a000) = 0x3f3838a000

mmap(0x3f3838f000, 18696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3f3838f000

close(3)                                = 0

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2dc78c1000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2dc78c0000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2dc78bf000

arch_prctl(ARCH_SET_FS, 0x7f2dc78c0700) = 0

mprotect(0x3f3838a000, 16384, PROT_READ) = 0

mprotect(0x3f37a1f000, 4096, PROT_READ) = 0

munmap(0x7f2dc78c2000, 70566)           = 0

brk(0)                                  = 0x1274000

brk(0x1295000)                          = 0x1295000

open("/usr/lib/locale/locale-archive", O_RDONLY) = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=99154480, ...}) = 0

mmap(NULL, 99154480, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f2dc1a2f000

close(3)                                = 0

getpgrp()                               = 2743              -- 获取进程组 id

getpid()                                = 2744              -- 获取进程 id

setsid()                                = 2744              -- 创建新的会话

execve("/usr/lib64/qt-3.3/bin/sleep", ["sleep", "10"], [/* 28 vars */]) = -1 ENOENT (No such file or directory)

execve("/usr/local/sbin/sleep", ["sleep", "10"], [/* 28 vars */]) = -1 ENOENT (No such file or directory)

execve("/usr/local/bin/sleep", ["sleep", "10"], [/* 28 vars */]) = -1 ENOENT (No such file or directory)

execve("/sbin/sleep", ["sleep", "10"], [/* 28 vars */]) = -1 ENOENT (No such file or directory)

execve("/bin/sleep", ["sleep", "10"], [/* 28 vars */]) = 0

brk(0)                                  = 0x1f96000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f60207fc000

access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)

open("/etc/ld.so.cache", O_RDONLY)      = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=70566, ...}) = 0

mmap(NULL, 70566, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f60207ea000

close(3)                                = 0

open("/lib64/libc.so.6", O_RDONLY)      = 3

read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\356\0018?\0\0\0"..., 832) = 832

fstat(3, {st_mode=S_IFREG|0755, st_size=1926760, ...}) = 0

mmap(0x3f38000000, 3750152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3f38000000

mprotect(0x3f3818a000, 2097152, PROT_NONE) = 0

mmap(0x3f3838a000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18a000) = 0x3f3838a000

mmap(0x3f3838f000, 18696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3f3838f000

close(3)                                = 0

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f60207e9000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f60207e8000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f60207e7000

arch_prctl(ARCH_SET_FS, 0x7f60207e8700) = 0

mprotect(0x3f3838a000, 16384, PROT_READ) = 0

mprotect(0x3f37a1f000, 4096, PROT_READ) = 0

munmap(0x7f60207ea000, 70566)           = 0

brk(0)                                  = 0x1f96000

brk(0x1fb7000)                          = 0x1fb7000

open("/usr/lib/locale/locale-archive", O_RDONLY) = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=99154480, ...}) = 0

mmap(NULL, 99154480, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f601a957000

close(3)                                = 0

nanosleep({10, 0}, NULL)                = 0                 -- 对应 sleep 10

close(1)                                = 0

close(2)                                = 0

exit_group(0)                           = ?

[root@YOYO ~]#

跟踪 nohup 的使用,可以看到内部设置了对 SIGHUP 信号的忽略处理。 

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

[root@YOYO ~]# strace nohup sleep 10 &

[1] 763

[root@YOYO ~]# execve("/usr/bin/nohup", ["nohup", "sleep", "10"], [/* 28 vars */]) = 0

brk(0)                                  = 0x138b000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f41c123d000

access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)

open("/etc/ld.so.cache", O_RDONLY)      = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=70566, ...}) = 0

mmap(NULL, 70566, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f41c122b000

close(3)                                = 0

open("/lib64/libc.so.6", O_RDONLY)      = 3

read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\356\0018?\0\0\0"..., 832) = 832

fstat(3, {st_mode=S_IFREG|0755, st_size=1926760, ...}) = 0

mmap(0x3f38000000, 3750152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3f38000000

mprotect(0x3f3818a000, 2097152, PROT_NONE) = 0

mmap(0x3f3838a000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18a000) = 0x3f3838a000

mmap(0x3f3838f000, 18696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3f3838f000

close(3)                                = 0

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f41c122a000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f41c1229000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f41c1228000

arch_prctl(ARCH_SET_FS, 0x7f41c1229700) = 0

mprotect(0x3f3838a000, 16384, PROT_READ) = 0

mprotect(0x3f37a1f000, 4096, PROT_READ) = 0

munmap(0x7f41c122b000, 70566)           = 0

brk(0)                                  = 0x138b000

brk(0x13ac000)                          = 0x13ac000

open("/usr/lib/locale/locale-archive", O_RDONLY) = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=99154480, ...}) = 0

mmap(NULL, 99154480, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f41bb398000

close(3)                                = 0

ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig -icanon -echo ...}) = 0

ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig -icanon -echo ...}) = 0

ioctl(2, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig -icanon -echo ...}) = 0

open("/dev/null", O_WRONLY)             = 3                      -- 以“只写”权限打开 /dev/null

dup2(3, 0)                              = 0                      -- 将标准输入重定向到 /dev/null

close(3)                                = 0

umask(037777777177)                     = 022

open("nohup.out", O_WRONLY|O_CREAT|O_APPEND, 0600) = 3           -- 打开 nohup.out 文件

dup2(3, 1)                              = 1                      -- 将标准输出重定向到 nohup.out

close(3)                                = 0

umask(022)                              = 0177

open("/usr/share/locale/locale.alias", O_RDONLY) = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=2512, ...}) = 0

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f41c123c000

read(3, "# Locale name alias data base.\n#"..., 4096) = 2512

read(3, "", 4096)                       = 0

close(3)                                = 0

munmap(0x7f41c123c000, 4096)            = 0

open("/usr/share/locale/zh_CN.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)

open("/usr/share/locale/zh_CN.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)

open("/usr/share/locale/zh_CN/LC_MESSAGES/coreutils.mo", O_RDONLY) = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=286636, ...}) = 0

mmap(NULL, 286636, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f41bb352000

close(3)                                = 0

open("/usr/lib64/gconv/gconv-modules.cache", O_RDONLY) = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=26060, ...}) = 0

mmap(NULL, 26060, PROT_READ, MAP_SHARED, 3, 0) = 0x7f41bb34b000

close(3)                                = 0

write(2, "nohup: ", 7nohup: )                  = 7

write(2, "\345\277\275\347\225\245\350\276\223\345\205\245\345\271\266\346\212\212\350\276\223\345\207\272\350\277\275\345\212\240\345\210"..., 44忽略输入并把输出追加到"nohup.out") = 44

write(2, "\n", 1

)                       = 1

fcntl(2, F_DUPFD, 3)                    = 3

fcntl(3, F_GETFD)                       = 0

fcntl(3, F_SETFD, FD_CLOEXEC)           = 0

dup2(1, 2)                              = 2                       -- 将标准出错重定向到 nohuo.out

rt_sigaction(SIGHUP, {SIG_IGN, [HUP], SA_RESTORER|SA_RESTART, 0x3f380326a0}, {SIG_DFL, [], 0}, 8) = 0     -- 设置 SIGHUP 信号处理函数为 SIG_IGN

execve("/usr/lib64/qt-3.3/bin/sleep", ["sleep", "10"], [/* 28 vars */]) = -1 ENOENT (No such file or directory)

execve("/usr/local/sbin/sleep", ["sleep", "10"], [/* 28 vars */]) = -1 ENOENT (No such file or directory)

execve("/usr/local/bin/sleep", ["sleep", "10"], [/* 28 vars */]) = -1 ENOENT (No such file or directory)

execve("/sbin/sleep", ["sleep", "10"], [/* 28 vars */]) = -1 ENOENT (No such file or directory)

execve("/bin/sleep", ["sleep", "10"], [/* 28 vars */]) = 0

brk(0)                                  = 0x86a000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc801ecc000

access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)

open("/etc/ld.so.cache", O_RDONLY)      = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=70566, ...}) = 0

mmap(NULL, 70566, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fc801eba000

close(3)                                = 0

open("/lib64/libc.so.6", O_RDONLY)      = 3

read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\356\0018?\0\0\0"..., 832) = 832

fstat(3, {st_mode=S_IFREG|0755, st_size=1926760, ...}) = 0

mmap(0x3f38000000, 3750152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3f38000000

mprotect(0x3f3818a000, 2097152, PROT_NONE) = 0

mmap(0x3f3838a000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18a000) = 0x3f3838a000

mmap(0x3f3838f000, 18696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3f3838f000

close(3)                                = 0

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc801eb9000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc801eb8000

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc801eb7000

arch_prctl(ARCH_SET_FS, 0x7fc801eb8700) = 0

mprotect(0x3f3838a000, 16384, PROT_READ) = 0

mprotect(0x3f37a1f000, 4096, PROT_READ) = 0

munmap(0x7fc801eba000, 70566)           = 0

brk(0)                                  = 0x86a000

brk(0x88b000)                           = 0x88b000

open("/usr/lib/locale/locale-archive", O_RDONLY) = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=99154480, ...}) = 0

mmap(NULL, 99154480, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fc7fc027000

close(3)                                = 0

nanosleep({10, 0}, NULL)                = 0                  -- 对应 sleep 10

close(1)                                = 0

close(2)                                = 0

exit_group(0)                           = ?

 

 

[1]+  Done                    strace nohup sleep 10

[root@YOYO ~]#

setsid 和 nohup 的源码实现

      通过上面的 strace 输出没有看出,为何通过 setsid 方式启动的程序不会因为 SIGHUP 信号退出的原因(但从理论上讲,我们知道是因为创建的进程没有控制终端的缘故)。下面看一下这两命令的源码实现。 

下面是 setsid 的核心源码(取自 util-linux-2.26) 
 
下面给出 nohup 的核心源码(取自 coreutils-8.24) 
 
 
 
可以看到,源码实现中的逻辑与 strace 看到的内容完全对应上了。 

部署工具脚本中的问题

      基于以上的内容,就可以很容易发现或解释我们实际使用中的脚本存在哪些问题(公司内容,略)。 

时间: 2024-09-30 15:20:41

【原创】Linux 下程序后台运行相关问题总结的相关文章

windows下cmd命令提示符下让程序后台运行命令

windows下cmd命令提示符下让程序后台运行命令 如果你的程序需要在windows后台运行,并且是在cmd下启动,那么在执行的程序前加上start /b,比如start /b [程序名]. windows下start命令的详细参数及功能介绍如下: 启动一个单独的窗口运行指定的程序或命令. START ["title"] [/D path] [/I] [/MIN] [/MAX] [/SEPARATE | /SHARED]      [/LOW | /NORMAL | /HIGH |

php判断linux下程序问题实例_php技巧

本文实例讲述了php判断linux下程序问题.分享给大家供大家参考.具体如下: 有时候在服务器上面写一些脚本的时候,经常要放到crontab里面定时运行.时间长了就有一个问题,那就是程序重复运行消耗太多的资源,怎么处理呢?下面璞玉写了两种方法. //第一种:用linux里面的正则匹配 function ifrun($clsname,$bf = 0) { //下面进行检测,如有一个进程正在运行,则不运行 $str=shell_exec("/bin/ps ax > /home/root/&qu

linux-Windows和Linux下程序的区别

问题描述 Windows和Linux下程序的区别 Windows和Linux下程序的区别Windows和Linux下程序的区别Windows和Linux下程序的区别Windows和Linux下程序的区别 解决方案 Windows主要针对x86,而Linux就丰富多了.不同的平台首先CPU指令都不一样.假设都是x86的,那么首先可执行文件的装配形式就不一样,windows是pe,linux是lef然后使用的api也不同. 解决方案二: windows下的应用程序在运行时要.net framewor

linux下多线程,运行显示connect:address already in use

问题描述 linux下多线程,运行显示connect:address already in use linux下多线程,运行显示connect:address already in use 什么情况-- 解决方案 报错信息为,端口被占用. 多线程访问的时候,记得及时的释放链接.并且你可以调一下链接数,调大一些.至少要比你线程数大. 解决方案二: Address already in use: connect解决 Address already in use: connect 的错误Tomcat报

代码-linux应用程序的运行流程 求详解

问题描述 linux应用程序的运行流程 求详解 事情是这样的,老师给了个作业(如下),因为课程时间等原因,开始想要啃下2.6源码的,在各种深度了解,剖析 巴拉巴拉等的linux电子书里并没有看出多大的头绪,讲到看源码更是头大,加之时间有限,所以并没有时间去仔细的研读,想要请各位大神给些指导,毕竟看到操作系统的庞大代码就不知道从哪里入手了. 如果有耐心+时间的话 更希望能够给出一些具体的解题入手步骤,如:怎么去跟踪程序的函数运行,函数间调用大概关系是怎么研究... 请不要嫌弃...知识掌握有限,想

j2me程序后台运行的问题

问题描述 如何实现,让j2me程序后台运行,就是说程序可以像手机qq那样,可以让程序在后台执行而看不到.试了几个例子都不能实现,一按挂起键就退出程序了. 解决方案 解决方案二:在jad文件和jar包的配置文件里加Background:True FlipInsensitive:True MIDxlet-Resident:Y的方法试过了还是不行解决方案三:挂起键就是退出的.解决方案四:midp1.0.2.0和2.1本不支持midlet后台运行,这里就看各个厂商的扩展功能了,索爱的有些还支持多midl

防火墙-php如何让程序后台运行

问题描述 php如何让程序后台运行 下面的代码是先让别人手机的能够访问网络,但是我想通过nohup在60分钟后将防火墙内的记录删除,以达到别人每60分钟必须重新连接一次网络. <?php $iipp=$_SERVER["REMOTE_ADDR"]; exec ("iptables -t nat -I PREROUTING -s $iipp -j ACCEPT"); exec ("nohup sleep 60m >/dev/null 2>&

ios两个用户聊天,程序后台运行的事后,为什么不能收到推送?

问题描述 ios两个用户聊天,程序后台运行的后,为什么不能收到推送?证书上传了,证书注册的代码也都写了,运行程序的时候也提醒是否设置推送点了确定了,就是收不到消息!什么情况? 解决方案 推送证书是APNS,apns是在应用被杀掉后才会走.在后台的时候需要自己写本地通知.参考demo里面mainvc  didreceivemssage里面的处理.

Windows 8如何在Metro界面下打开后台运行的程序

  操作步骤: 一.手势触摸 在屏幕的左边框位置向右滑动,即可拖出后台运行的程序. 二.鼠标操作 鼠标移动到左上角即可出现一个栏,里边是打开的所有程序,点击相应的程序即可. 备注: 备注:按windows键可以在最近打开的两个程序之间切换.