V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
alwayshere
V2EX  ›  程序员

想让 PHP cli 执行一个较长的任务, xshell 一关闭, nohup 也跟着退出了,怎么回事?

  •  
  •   alwayshere · 2017-03-16 14:20:28 +08:00 · 5572 次点击
    这是一个创建于 2836 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前用 php cli 模式爬取一个网站内容,因为要执行很久,在 xshell 中输入:

    nohup php scrape.php &

    回车后, php 继续执行,但是一关闭 xshell ,这个进程也就跟着结束了, nohup 这么脆弱吗? Linux 小白不太懂,求好心 V2 们解答一下,或者有没有更好的让 php 常驻进程的命令?

    第 1 条附言  ·  2017-03-16 16:01:09 +08:00
    刚刚手上三台服务器测试了一下,其中两台服务器 xshell 右上角叉叉关闭了, nohup 进程继续执行,另外一台服务器 xshell 右上角叉叉关闭后, nohup 进程终止,但是如果在 xshell 中 exit 后,再右上角叉叉, nohup 进程却能继续存活,这是何解?三台服务器都是 centos 6.8
    27 条回复    2017-03-16 23:44:20 +08:00
    emuhuang
        1
    emuhuang  
       2017-03-16 14:24:06 +08:00
    at ?
    torbrowserbridge
        2
    torbrowserbridge  
       2017-03-16 14:24:23 +08:00 via iPhone
    screen / tmux
    alwayshere
        3
    alwayshere  
    OP
       2017-03-16 14:36:22 +08:00
    @emuhuang 什么意思?
    loading
        4
    loading  
       2017-03-16 14:37:51 +08:00 via Android
    2 楼 +1
    gouchaoer
        5
    gouchaoer  
       2017-03-16 14:42:24 +08:00
    不可能,你先开 error_log 或者 coredump 把原因搞清楚
    gouchaoer
        6
    gouchaoer  
       2017-03-16 14:42:29 +08:00
    http://www.bo56.com/一个 echo 引起的进程崩溃 /
    spkinger
        7
    spkinger  
       2017-03-16 14:53:48 +08:00
    用 Supervisor 守护进程,挂了它会尝试重启
    Hello1995
        8
    Hello1995  
       2017-03-16 15:01:30 +08:00 via Android
    screen 。另外,如果就一台机器长时间在抓,不用高匿代理访问很容易被拉黑……
    lcdtyph
        9
    lcdtyph  
       2017-03-16 15:03:21 +08:00
    不想麻烦的话就
    setsid nohup php scrape.php &
    Biny
        10
    Biny  
       2017-03-16 15:07:30 +08:00
    dnf install screen
    elarity
        11
    elarity  
       2017-03-16 15:12:51 +08:00
    <?php
    // fork 一个 php 进程
    $pid = pcntl_fork();
    if ($pid < 0)
    exit(' fork error. ');
    else if ($pid)
    exit(' I am the parent process ');
    else {
    // I am the child process
    $sid = posix_setsid();
    if ($sid < 0)
    exit;
    for($i = 0; $i <= 60; $i++) {
    echo "echo Hello world from PHP daemon.".PHP_EOL;
    sleep(5);
    }
    }



    使用 posix_setsid 是至关重要的一步了,上面的代码助你完成 php 脚本 daemon 的完成,不需要借助其他力量,注意骚年,不要搞成僵尸进程
    iyaozhen
        12
    iyaozhen  
       2017-03-16 15:23:45 +08:00 via Android
    但是一关闭 xshell ,这个进程也就跟着结束了
    不肯能啊,我一直这样用,一般场景你这种做法就行了。是不是 PHP 自己报错了
    w3sy
        13
    w3sy  
       2017-03-16 15:30:51 +08:00
    http://www.cnblogs.com/allenblogs/archive/2011/05/19/2051136.html
    我才发现我和他操作终端时的一个细节不同:他是在当 shell 中提示了 nohup 成功后还需要按终端上键盘任意键退回到 shell 输入命令窗口,然后通过在 shell 中输入 exit 来退出终端;而我是每次在 nohup 执行成功后直接点关闭程序按钮关闭终端.。所以这时候会断掉该命令所对应的 session ,导致 nohup 对应的进程被通知需要一起 shutdown 。
    gouchaoer
        14
    gouchaoer  
       2017-03-16 15:32:50 +08:00
    @elarity 教科书般的错误,你需要 2 次 fork 。。。参考这个: https://yangxikun.github.io/linux/2013/11/11/linux-process.html
    alwayshere
        15
    alwayshere  
    OP
       2017-03-16 15:34:15 +08:00
    @iyaozhen 我手上另外两台服务器都可以 xshell 关闭后, nohup 继续执行,就这个装一样的 centos 6.8 系统, xshell 一关闭,马上就退出 php 进程,测试了好多次都是这样,必须把 xshell 挂起
    elarity
        16
    elarity  
       2017-03-16 15:58:12 +08:00
    @gouchaoer yes ! I know , 我直接从 posix_setsid 的手册下搞过来这段 code ,旨在告诉小朋友 setsid ,多谢指正,误导了不少好骚年
    SummerWQM
        17
    SummerWQM  
       2017-03-16 16:03:06 +08:00
    这种建议 使用 supervisord 吧
    lululau
        18
    lululau  
       2017-03-16 16:06:00 +08:00
    5L +1
    TIGERB
        19
    TIGERB  
       2017-03-16 16:24:49 +08:00
    tmux
    HowToMakeLove
        20
    HowToMakeLove  
       2017-03-16 16:54:01 +08:00
    nohup command & 后,需要敲回车退出到 bash 、然后再退出
    alwayshere
        21
    alwayshere  
    OP
       2017-03-16 17:01:18 +08:00
    @HowToMakeLove 我是这样做的,连按两次回车,直接右上角关闭 xshell ,然后那个 php 进程也立即终止了
    chenqh
        22
    chenqh  
       2017-03-16 17:09:50 +08:00
    screen?
    minbaby
        23
    minbaby  
       2017-03-16 17:43:59 +08:00
    这种需求有这么几种做法
    1. tmux/screen/byobu(简单)这些工具,可以吧你正在用的会话一直保持下去
    2. 使用 supervisor 这类守护进程工具,可以帮助你自己启动,或者重新启动程序(推荐)
    3. 自己实现 daemon 功能(参考 https://github.com/minbaby/http-server-learning/blob/master/sample/how_to_make_daemon/daemon.php)
    Jaylee
        24
    Jaylee  
       2017-03-16 18:05:32 +08:00
    @minbaby 两次 fork
    minbaby
        25
    minbaby  
       2017-03-16 19:13:17 +08:00
    @Jaylee 翻了一下 unix 环境编程的 守护进程那一章,确实是进行了两次 fork ,不过中间有提到, System V 系统有人建议进行两次 fork ,以防止其获取终端控制。不过这似乎并不是必须的吧?
    IgniteWhite
        26
    IgniteWhite  
       2017-03-16 19:26:46 +08:00
    screen
    eoo
        27
    eoo  
       2017-03-16 23:44:20 +08:00 via Android
    pm2
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2330 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 15:59 · PVG 23:59 · LAX 07:59 · JFK 10:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.