简单的 bash 脚本按名称计算正在运行的进程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12393437/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 03:15:44  来源:igfitidea点击:

Simple bash script count running processes by name

bashsshcron

提问by Mr.Boon

i'm working on a small bash script which counts how often a script with a certain name is running.

我正在研究一个小的 bash 脚本,它计算具有特定名称的脚本运行的频率。

ps -ef | grep -v grep | grep scrape_data.php | wc -l

is the code i use, via ssh it outputs the number of times scrape_data.php is running. Currently the output is 3 for example. So this works fine.

是我使用的代码,它通过 ssh 输出 scrape_data.php 运行的次数。例如,当前输出为 3。所以这很好用。

Now I'm trying to make a little script which does somethingwhen the count is smaller than 1.

现在我正在尝试制作一个小脚本,当计数小于 1 时它会做一些事情

#!/bin/sh


if [ ps -ef | grep -v grep | grep scrape_data.php | wc -l ] -lt 1; then
        exit 0

 #HERE PUT CODE TO START NEW PROCESS

else

        exit 0
fi

The script above is what I have so far, but it does not work. I'm getting this error:

上面的脚本是我到目前为止所拥有的,但它不起作用。我收到此错误:

[root@s1 crons]# ./check_data.sh
./check_data.sh: line 4: [: missing `]'
wc: invalid option -- e

What am I doing wrong in the if statement?

我在 if 语句中做错了什么?

回答by perreal

Your test syntax is not correct, the ltshould be within the test bracket:

您的测试语法不正确,lt应该在测试括号内:

if [ $(ps -ef | grep -v grep | grep scrape_data.php | wc -l) -lt 1 ]; then

  echo launch

else
  echo no launch

  exit 0
fi

or you can test the return value of pgrep:

或者您可以测试的返回值pgrep

pgrep scrape_data.php &> /dev/null

if [ $? ]; then
  echo no launch
fi

回答by c00kiemon5ter

if you're using Bashthen drop [and -ltand use ((for arithmetic comparisons.

如果你使用Bash然后删除[,并-lt和使用((的算术比较。

psprovides the -Cswitch, which accepts the process name to look for.
grep -vtrickery are just hacks.

ps提供-C开关,它接受要查找的进程名称。
grep -v诡计只是黑客。

#!/usr/bin/env bash

proc="scrape_data.php"
limit=1

numproc="$(ps hf -opid,cmd -C "$proc" | awk ' !~ /^[|\]/ { ++n } END { print n }')"

if (( numproc < limit ))
then
    # code when less than 'limit' processes run
    printf "running processes: '%d' less than limit: '%d'.\n" "$numproc" "$limit"
else
    # code when more than 'limit' processes run
    printf "running processes: '%d' more than limit: '%d'.\n" "$numproc" "$limit"
fi

回答by choroba

Counting the lines is not needed. Just check the return value of grep:

不需要计算行数。只需检查的返回值grep

if ! ps -ef | grep -q '[s]crape_data.php' ; then 
    ...
fi

The [s] trick avoids the grep -v grep.

[s] 技巧避免了grep -v grep.

回答by Thomas Kroll

While the top-voted answer does in fact work, I have a solution that I used for my scraper that worked for me.

虽然最高投票的答案确实有效,但我有一个用于我的刮板的解决方案,它对我有用。

<?php

/**
 *  Go_Get.php
 *  -----------------------------------------
 *  @author Thomas Kroll
 *  @copyright Creative Commons share alike.
 *  
 *  @synopsis:
 *      This is the main script that calls the grabber.php
 *      script that actually handles the scraping of 
 *      the RSI website for potential members
 *
 *  @usage:  php go_get.php
 **/

    ini_set('max_execution_time', 300); //300 seconds = 5 minutes


    // script execution timing
    $start = microtime(true);

    // how many scrapers to run
    $iter = 100;

    /**
     * workload.txt -- next record to start with
     * workload-end.txt -- where to stop at/after
     **/

    $s=(float)file_get_contents('./workload.txt');
    $e=(float)file_get_contents('./workload-end.txt');

    // if $s >= $e exit script otherwise continue
    echo ($s>=$e)?exit("Work is done...exiting".PHP_EOL):("Work is not yet done...continuing".PHP_EOL);

    echo ("Starting Grabbers: ".PHP_EOL);

    $j=0;  //gotta start somewhere LOL
    while($j<$iter)
    {
        $j++;
        echo ($j %20!= 0?$j." ":$j.PHP_EOL);

        // start actual scraping script--output to null
        // each 'grabber' goes and gets 36 iterations (0-9/a-z)
        exec('bash -c "exec nohup setsid php grabber.php '.$s.' > /dev/null 2>&1 &"');

        // increment the workload counter by 36 characters              
        $s+=36;
    }
    echo PHP_EOL;
    $end = microtime(true);
    $total = $end - $start;
    print "Script Execution Time: ".$total.PHP_EOL;

    file_put_contents('./workload.txt',$s);

    // don't exit script just yet...
    echo "Waiting for processes to stop...";

    // get number of php scrapers running
    exec ("pgrep 'php'",$pids);
    echo "Current number of processes:".PHP_EOL;

    // loop while num of pids is greater than 10
    // if less than 10, go ahead and respawn self
    // and then exit.
    while(count($pids)>10)
    {
        sleep(2);
        unset($pids);
        $pids=array();
        exec("pgrep 'php'",$pids);
        echo (count($pids) %15 !=0 ?count($pids)." ":count($pids).PHP_EOL);
    }

    //execute self before exiting
    exec('bash -c "exec nohup setsid php go_get.php >/dev/null 2>&1 &"');
    exit();
?>

Now while this seems like a bit of overkill, I was already using PHP to scrape the data (like your php script in the OP), so why not use PHP as the control script?

现在虽然这看起来有点矫枉过正,但我​​已经在使用 PHP 来抓取数据(就像你在 OP 中的 php 脚本),那么为什么不使用 PHP 作为控制脚本呢?

Basically, you would call the script like this:

基本上,您可以这样调用脚本:

php go_get.php

php go_get.php

and then just wait for the first iteration of the script to finish. After that, it runs in the background, which you can see if you use your pid counting from the command line, or a similar tool like htop.

然后等待脚本的第一次迭代完成。之后,它在后台运行,您可以查看是否使用命令行中的 pid 计数,或类似的工具,如htop.

It's not glamorous, but it works. :)

它并不迷人,但它有效。:)