首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP pcntl_fork 多進程下載圖片實作(僅限 Linux CLI)

     編輯:PHP 綜合知識

前置條件

  • Linux 環境(Windows 不支援 pcntl 擴展)。
  • PHP 安裝 pcntl 擴展:pecl install pcntl 或原始碼編譯 --enable-pcntl。
  • 僅能在 CLI 模式 執行(Web/FPM 進程禁止 fork)。

核心原理

$pid = pcntl_fork();
if ($pid === -1) { die('fork 失敗'); }
elseif ($pid > 0) { /* 父進程:繼續派發任務或等待 */ }
else { /* 子進程:執行具體下載任務 */ }
  • 父進程取得子進程 PID(>0)。
  • 子進程取得 0。
  • 父子進程複製當前記憶體空間(Copy-on-Write),各自獨立執行。

完整多進程下載範例

<?php
// download_images.php
$url = 'https://example.com/gallery';
$html = file_get_contents($url);
preg_match_all('/ $imgUrl) {
    $pid = pcntl_fork();
    if ($pid === -1) { echo "fork 失敗\n"; continue; }
    if ($pid === 0) {
        // 子進程
        download_one($url, $imgUrl);
        exit(0); // 關鍵:子進程必須 exit,否則會繼續迴圈產生孫進程
    }
    $pids[] = $pid;
}

// 父進程等待所有子進程結束
foreach ($pids as $pid) {
    pcntl_waitpid($pid, $status);
}

echo "下載完成,耗時 " . round(microtime(true)-$start,2) . " 秒\n";

function download_one($base, $src) {
    // 處理相對/絕對路徑
    if (strpos($src, '//') === 0) $src = 'https:'.$src;
    elseif (!preg_match('#^https?://#', $src)) $src = rtrim($base,'/').'/'.ltrim($src,'/');

    $data = @file_get_contents($src);
    if ($data === false) return;

    $fname = basename(parse_url($src, PHP_URL_PATH));
    $fname = preg_replace('/[^a-zA-Z0-9._-]/','_',$fname);
    $path = sys_get_temp_dir().'/img_dl/'.$fname;
    @mkdir(dirname($path), 0777, true);
    file_put_contents($path, $data);
    echo "[$$] saved $fname\n";
}

關鍵細節

點說明
子進程 exit(0)避免子進程繼續執行父進程迴圈,產生指數級進程爆炸
父進程 pcntl_waitpid回收子進程資源,避免殭屍進程;可加 WNOHANG 非阻塞輪詢
錯誤處理下載失敗靜默返回,不影響其他子進程
並發控制大量圖片時建議加入 semaphore 或 proc_open 池限制同時進程數(如 10-20)
信號處理註冊 pcntl_signal(SIGTERM, ...) 優雅關閉

生產級替代方案

  • Guzzle + Promise:非阻塞並發 HTTP,單進程高效能,無 fork 開銷。
  • Swoole / OpenSwoole:協程並發,原生支援 HTTP Client、Channel、Process 池。
  • Gearman / RabbitMQ + Worker:分散式任務隊列,跨機器擴展。

pcntl_fork 適合快速腳本、無依賴環境;長期專案建議遷移至協程/非阻塞架構。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved