终止通过 PHP system() 函数运行的 top 命令

如何结束,通过 PHP 语言 的 SYSTEM 函数 运行 的 持续性结果 输出型 系统命令 呢?

本文章仅提供学习,切勿将其用于不法手段!

当 PHP 的 system() 函数执行了 top 命令时,这个命令会持续运行并占用终端。以下是专业解决方案,分为立即终止方法和预防措施:

立即终止方法

1. 通过进程管理终止(推荐)

# 查找 top 进程的 PID
ps aux | grep 'top' | grep -v grep

# 示例输出:
# www-data 12345  0.5  0.1  12345  6789 ?        S    12:34   0:00 top

# 终止进程
sudo kill -9 12345

2. 通过 pkill 直接终止

# 终止所有由 www-data 运行的 top 进程
sudo pkill -u www-data top

3. PHP 内部终止(如果仍有 PHP 执行权限)

<?php
// 查找并终止 top 进程
exec("pgrep -u www-data top", $pids);
foreach ($pids as $pid) {
    posix_kill($pid, 9); // SIGKILL
    echo "已终止进程: $pid\n";
}
?>

预防措施:安全执行命令的方法

1. 使用超时机制

<?php
// 使用 GNU timeout 命令限制执行时间
system('timeout 5 top'); // 5秒后自动终止
?>

2. 使用 proc_open 控制进程

<?php
$descriptors = [
    0 => ['pipe', 'r'], // stdin
    1 => ['pipe', 'w'], // stdout
    2 => ['pipe', 'w']  // stderr
];

$process = proc_open('top', $descriptors, $pipes);

if (is_resource($process)) {
    // 5秒后终止进程
    sleep(5);
    
    // 获取进程状态
    $status = proc_get_status($process);
    
    // 如果进程仍在运行则终止
    if ($status['running']) {
        proc_terminate($process, 9); // SIGKILL
    }
    
    // 关闭所有管道
    foreach ($pipes as $pipe) {
        fclose($pipe);
    }
    
    // 关闭进程
    proc_close($process);
}
?>

3. 使用 Symfony Process 组件(更安全)

<?php
require_once 'vendor/autoload.php';

use Symfony\Component\Process\Process;

$process = new Process(['top']);
$process->setTimeout(5); // 5秒超时
$process->start();

// 等待进程结束或超时
while ($process->isRunning()) {
    usleep(100000); // 100ms
    // 可在此添加终止条件
}

// 如果超时后仍在运行,强制终止
if ($process->isRunning()) {
    $process->signal(9); // SIGKILL
}
?>

高级场景:后台进程管理

1. 创建可管理的后台进程

<?php
// 启动后台 top 进程并记录 PID
$pid = shell_exec('nohup top -b > /dev/null 2>&1 & echo $!');
file_put_contents('top.pid', $pid);

// 需要终止时
$pid = file_get_contents('top.pid');
exec("kill -9 $pid");
?>

2. 使用 Supervisor 管理

; /etc/supervisor/conf.d/top.conf
[program:php_top]
command=top -b
user=www-data
autostart=false
autorestart=false
stderr_logfile=/var/log/top.err.log
stdout_logfile=/var/log/top.out.log

PHP 控制代码:

<?php
// 启动
shell_exec('sudo supervisorctl start php_top');

// 停止
shell_exec('sudo supervisorctl stop php_top');

安全注意事项

  1. 权限最小化​:

    # 设置 sudo 权限限制
    www-data ALL=(root) NOPASSWD: /usr/bin/supervisorctl start php_top, /usr/bin/supervisorctl stop php_top
  2. 输入验证​:

    <?php
    $allowedCommands = ['top', 'htop', 'iotop'];
    $command = $_GET['cmd'];
    
    if (in_array($command, $allowedCommands)) {
        system('timeout 5 '.escapeshellarg($command));
    }
    ?>
  3. 禁用危险函数​:

    ; php.ini
    disable_functions = system, exec, passthru, shell_exec, proc_open, popen
  4. 使用 PHP-FPM 池限制​:

    ; www-data 进程池配置
    pm = dynamic
    pm.max_children = 10
    pm.start_servers = 2
    pm.min_spare_servers = 1
    pm.max_spare_servers = 5

替代方案:使用系统状态 API

<?php
// 使用 sys_getloadavg() 替代 top
$load = sys_getloadavg();
echo "1分钟负载: {$load[0]}\n";
echo "5分钟负载: {$load[1]}\n";
echo "15分钟负载: {$load[2]}\n";

// 使用 /proc 文件系统
$meminfo = file_get_contents('/proc/meminfo');
preg_match('/MemTotal:\s+(\d+)/', $meminfo, $matches);
$totalMem = round($matches[1] / 1024); // MB

// 使用 shell_exec 安全获取信息
$uptime = shell_exec('uptime -p');
$disk = shell_exec('df -h /');
?>

通过以上方法,您可以安全地管理和终止通过 PHP system() 函数执行的 top 命令,同时确保系统安全性和稳定性。

道可道,非常道,名可名,非常名。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值