V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
dyllen
V2EX  ›  Linux

pgrep 命令是不是有什么问题?加-f 参数 pid 每次都变

  •  
  •   dyllen · 2023-07-31 14:32:38 +08:00 · 1398 次点击
    这是一个创建于 485 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在 shell 脚本里面这样获取 pid:

    pid=`pgrep $projectName`
    echo "'$pid'"
    

    发现有字符长度限制,太长返回空,后面改成这样:

    pid=`pgrep -f $projectName`
    echo "'$pid'"
    

    问题来了加了-f参数后,获取到的 pid 的值变这样了:

    '3054607
    3206134'
    

    取到了两个 pid 值,第一个是正确的,第二个是完全不相干的,每次还变。 然后我杀死进程之后再执行,他还是能获取的一个完全不相关的 pid 出来。

    不管我要找的进程在不在他总是有值,还不一定对,我不用脚本执行,就在控制台执行单纯pgrep -f $projectName就没问题。

    这什么问题?

    第 1 条附言  ·  2023-07-31 16:25:21 +08:00

    下面是我测试的内容。

    我的测试脚本内容:

    #!/bin/bash
    
    set -e
    
    pid=`pgrep -f $1`
    echo "'$pid'"
    

    ./test.sh abc结果:

    ~$ ./test.sh abc
    '3234022
    3354825'
    
    ~$ ./test.sh abc
    '3234022
    3354899'
    
    ~$ ./test.sh abc
    '3234022
    3354906'
    

    控制台执行的输出结果:

    ~$ echo `pgrep -f abc`
    3234022
    
    ~$ echo `pgrep -f abc`
    3234022
    
    ~$ echo `pgrep -f abc`
    3234022
    

    ps -ef | grep除去 grep 的进程,就一个运行进程。

    这里我把名字用 abc 替换了,实际也是这么简单,英文字母下划线组成的 10 个字符长度的名字,没特殊字符。

    19 条回复    2023-08-06 11:51:57 +08:00
    lhbc
        1
    lhbc  
       2023-07-31 14:50:13 +08:00
    怀疑这么基础的软件有问题之前,还是先怀疑下你的参数和系统的进程列表比较好
    你给个变量谁知道什么情况啊
    lhbc
        2
    lhbc  
       2023-07-31 14:51:52 +08:00
    另外,如果同一个进程名称有多个进程,pgrep 是会获取到多个 pid 的
    liuchao719
        3
    liuchao719  
       2023-07-31 15:42:41 +08:00
    这个不想干的进程是不是就是 pgrep 本身?
    julyclyde
        4
    julyclyde  
       2023-07-31 15:49:07 +08:00
    @liuchao719 pgrep 会过滤掉 pgrep 自己的,不会发生你猜的这种情况

    第二个应该是线程号
    lhbc
        5
    lhbc  
       2023-07-31 15:50:40 +08:00
    @liuchao719 不会,pgrep 里有逻辑把自己的 pid 给去掉了
    dyllen
        6
    dyllen  
    OP
       2023-07-31 16:22:30 +08:00
    @lhbc 我肯定是对过了,才会来发问的。

    下面是我测试的内容。

    我的测试脚本内容:

    ```shell
    #!/bin/bash

    set -e

    pid=`pgrep -f $1`
    echo "'$pid'"
    ```
    `./test.sh abc`结果:
    ```shell
    ~$ ./test.sh abc
    '3234022
    3354825'

    ~$ ./test.sh abc
    '3234022
    3354899'

    ~$ ./test.sh abc
    '3234022
    3354906'
    ```

    控制台执行的输出结果:

    ```shell
    ~$ echo `pgrep -f abc`
    3234022

    ~$ echo `pgrep -f abc`
    3234022

    ~$ echo `pgrep -f abc`
    3234022
    ```

    `ps -ef | grep`出来出去 grep 的进程,就一个运行进程。

    这里我把名字用 abc 替换了,实际也是这么简单,英文字母下划线组成的 10 个字符长度的名字,没特殊字符。
    llh880808
        7
    llh880808  
       2023-07-31 16:30:14 +08:00
    提供一个思路,我这边做实验得到的结果是
    1. pgrep $name 得到 1 个结果
    2. pgrep -f $name 得到 2 个结果
    3. ps -ef | grep 多出来的那个 pid ,发现多出来的 pid 是 CMD 列包含`$name`字样(比如路径名包含),但并不是我预期的
    4. pgrep -h 查看-f 参数的含义是“ use full process name to match”,猜想,-f 参数会使用整个进程名(包括参数)去匹配,很容易匹配到预期外的结果
    dyllen
        8
    dyllen  
    OP
       2023-07-31 16:52:36 +08:00
    @llh880808 是加了-f 参数,得到两个结果,第二个完全不相干的 pid 了
    Alias4ck
        9
    Alias4ck  
       2023-07-31 16:55:27 +08:00
    感觉是你字符串的问题你可以-l 打印完整进程名看看

    dyllen
        10
    dyllen  
    OP
       2023-07-31 16:55:43 +08:00
    @llh880808 不加-f 参数,有长度限制,名称超过 15 个字符就匹配不出来了,搜索下来都是说加-f 参数解决,加了之后我发现会匹配出来两个结果。所以现在我是就截取前 15 个字符来匹配。。。这样暂时没问题。
    dyllen
        11
    dyllen  
    OP
       2023-07-31 16:58:13 +08:00
    @Alias4ck

    `test.sh`加了-l ,结果:

    ~$ ./test.sh abc
    '3234022 abc
    3403871 test.sh'


    第二个 pid 是脚本本身。
    Alias4ck
        12
    Alias4ck  
       2023-07-31 17:02:43 +08:00
    那就合理的解释了为啥每次都会变了 因为匹配到自身了

    找到一个跟你差不多的问题
    https://stackoverflow.com/questions/59790449/bash-script-strange-pgrep-behaviour
    lhbc
        13
    lhbc  
       2023-07-31 17:03:44 +08:00
    ./test.sh abc
    这个命令本身被匹配到了
    lhbc
        14
    lhbc  
       2023-07-31 17:09:23 +08:00
    不要把进程名称作为脚本的参数提交
    julyclyde
        15
    julyclyde  
       2023-07-31 19:33:35 +08:00
    不过这问题应该换个角度(不是可以,而是应该)
    你可能需要把这个进程托管给 systemd 管理,而不是自己寨一套脚本出来
    dyllen
        16
    dyllen  
    OP
       2023-08-03 11:21:23 +08:00
    @julyclyde 这又不是线上用的,就是为了方便自己开发重启应用用的,我那小脚本功能是拉取代码,编译,结束原来的进程,启动新的进程。
    dyllen
        17
    dyllen  
    OP
       2023-08-03 11:23:40 +08:00
    @lhbc 这就不太好了,那只能自己再过滤一遍结果了,或者只取前 15 个字符不加-f 参数来匹配了,这样也没有问题。
    julyclyde
        18
    julyclyde  
       2023-08-03 12:14:37 +08:00
    @dyllen 让旧进程自己写个 pid 文件吧
    dyllen
        19
    dyllen  
    OP
       2023-08-06 11:51:57 +08:00
    @julyclyde 这样也可以,pid 记录下来
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5467 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 07:44 · PVG 15:44 · LAX 23:44 · JFK 02:44
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.