ลดความยุ่งยากในการใช้คลาวด์ พูดคุยกับเจ้าหน้าที่

Home ติดตั้ง PHP หลายเวอร์ชันบน Ubuntu

ติดตั้ง PHP หลายเวอร์ชันบน Ubuntu

เว็บไซต์เก่าบางระบบยังต้องการ PHP 7.4 หรือ 8.1 ขณะที่เว็บใหม่ต้องการ PHP 8.3 ขึ้นไป แพ็กเกจมาตรฐานของ Ubuntu มี PHP ให้เพียงเวอร์ชันเดียวต่อรุ่นของระบบ (8.1 บน 22.04 และ 8.3 บน 24.04) หากต้องการรันหลายเวอร์ชันพร้อมกันบนเครื่องเดียว วิธีที่นิยมที่สุดคือใช้ PPA ondrej/php ร่วมกับ PHP-FPM แล้วให้แต่ละเว็บส่งงานไปยัง FPM ของเวอร์ชันที่ต้องการ

บทความนี้ติดตั้ง PHP 8.2 และ 8.3 คู่กัน กำหนดให้แต่ละเว็บใช้เวอร์ชันต่างกันทั้งบน Nginx และ Apache และเลือกเวอร์ชันของคำสั่ง php ใน Command Line หากคุณใช้ Plesk ให้เปลี่ยนเวอร์ชันผ่านหน้าจอของ Plesk แทน ตาม การเปลี่ยนเวอร์ชั่น PHP ใน Plesk อย่าติดตั้ง PPA ซ้อนบนเครื่องที่มี Control Panel

สิ่งที่ต้องเตรียม

  • Ubuntu 22.04 หรือ 24.04 ที่ไม่มี Control Panel และผู้ใช้ที่มีสิทธิ์ sudo
  • เว็บเซิร์ฟเวอร์ Nginx หรือ Apache ที่ติดตั้งแล้ว
  • สำรองข้อมูลเว็บและ Snapshot ของเครื่องก่อนเริ่ม เพราะการเพิ่ม PPA จะอัปเกรดแพ็กเกจ PHP เดิมของคุณด้วย

หมายเหตุ: PPA ondrej/php ดูแลโดย Ondřej Surý ผู้ดูแลแพ็กเกจ PHP ของ Debian ไม่ใช่ Canonical โดยตรง และรองรับเฉพาะ Ubuntu LTS ที่ยังอยู่ในระยะสนับสนุน PHP เวอร์ชันที่หมดอายุการดูแลจากทีม PHP (เช่น 7.4, 8.0 และ 8.1) ยังติดตั้งได้ แต่ไม่ได้รับแพตช์ความปลอดภัยอย่างเป็นทางการ ควรใช้เป็นการชั่วคราวระหว่างปรับโค้ดเท่านั้น ตรวจตารางอายุการสนับสนุนได้ที่ php.net/supported-versions.php

ขั้นตอนที่ 1: เพิ่ม PPA ondrej/php

sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository ppa:ondrej/php
sudo apt update

คำสั่ง add-apt-repository จะแสดงคำอธิบายของ PPA และให้กด Enter เพื่อยืนยัน เมื่อเสร็จ ตรวจว่าเห็นแพ็กเกจจาก PPA แล้ว:

apt-cache policy php8.2-fpm

บรรทัด Candidate ต้องมีเลขเวอร์ชัน และบรรทัดแหล่งที่มาควรมี ppa.launchpadcontent.net/ondrej/php

ขั้นตอนที่ 2: ติดตั้ง PHP แต่ละเวอร์ชันพร้อม FPM

ชื่อแพ็กเกจจะมีเลขเวอร์ชันนำหน้าเสมอ ต้องติดตั้งส่วนขยายแยกของแต่ละเวอร์ชัน:

sudo apt install -y php8.2-fpm php8.2-cli php8.2-mysql php8.2-curl \
  php8.2-gd php8.2-mbstring php8.2-xml php8.2-zip php8.2-intl

sudo apt install -y php8.3-fpm php8.3-cli php8.3-mysql php8.3-curl \
  php8.3-gd php8.3-mbstring php8.3-xml php8.3-zip php8.3-intl

ตรวจว่า FPM ทั้งสองทำงานและมี Socket แยกกัน:

systemctl status php8.2-fpm php8.3-fpm --no-pager | grep -E "fpm.service|Active"
ls -l /run/php/

ควรเห็น php8.2-fpm.sock และ php8.3-fpm.sock แต่ละเวอร์ชันมีไฟล์ตั้งค่าของตัวเองแยกกันทั้งหมด:

รายการตำแหน่ง (ตัวอย่าง PHP 8.2)
php.ini ของ FPM (เว็บ)/etc/php/8.2/fpm/php.ini
php.ini ของ CLI/etc/php/8.2/cli/php.ini
Pool ของ FPM/etc/php/8.2/fpm/pool.d/www.conf
Socket/run/php/php8.2-fpm.sock
ชื่อ Servicephp8.2-fpm

การแก้ memory_limit หรือ upload_max_filesize จึงต้องแก้ใน php.ini ของเวอร์ชันที่เว็บนั้นใช้ แล้วรีสตาร์ต Service ของเวอร์ชันนั้น เช่น sudo systemctl restart php8.2-fpm

ขั้นตอนที่ 3 (Nginx): กำหนดเวอร์ชันต่อเว็บ

ใน Server Block ของแต่ละเว็บ เปลี่ยนเฉพาะบรรทัด fastcgi_pass ให้ชี้ไปที่ Socket ของเวอร์ชันที่ต้องการ ตัวอย่างเว็บเก่าใช้ 8.2:

server {
    listen 80;
    server_name legacy.example.com;
    root /var/www/legacy.example.com/public;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    }
}

ส่วนเว็บใหม่ใช้ fastcgi_pass unix:/run/php/php8.3-fpm.sock; จากนั้นตรวจและโหลดค่าใหม่:

sudo nginx -t && sudo systemctl reload nginx

การตั้ง Server Block หลายเว็บอธิบายไว้ครบใน ตั้งค่า Nginx Server Block สำหรับหลายเว็บไซต์ในเครื่องเดียว

ขั้นตอนที่ 3 (Apache): เปลี่ยนจาก mod_php เป็น PHP-FPM

mod_php โหลด PHP ได้เพียงเวอร์ชันเดียวต่อ Apache ถ้าติดตั้ง LAMP ด้วย libapache2-mod-php มาก่อน ต้องสลับไปใช้ FPM ก่อน:

sudo a2dismod php8.3
sudo a2dismod mpm_prefork
sudo a2enmod mpm_event proxy_fcgi setenvif

ถ้า a2dismod php8.3 แจ้งว่าไม่มีโมดูลนี้ ให้ดูชื่อที่เปิดอยู่จริงด้วย apache2ctl -M | grep php จากนั้นใน VirtualHost ของแต่ละเว็บ เพิ่มบล็อกนี้โดยเลือก Socket ตามเวอร์ชัน:

<VirtualHost *:80>
    ServerName legacy.example.com
    DocumentRoot /var/www/legacy.example.com/public

    <FilesMatch \.php{{CONTENT}}gt;
        SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
    </FilesMatch>
</VirtualHost>

ตรวจไวยากรณ์และรีสตาร์ต (ต้อง restart เพราะเปลี่ยน MPM):

sudo apache2ctl configtest
sudo systemctl restart apache2

อย่าเปิด a2enconf php8.x-fpm ของหลายเวอร์ชันพร้อมกัน เพราะไฟล์เหล่านั้นตั้ง Handler ระดับทั้งเซิร์ฟเวอร์ และจะทับกันเอง การกำหนดใน VirtualHost อย่างเดียวชัดเจนกว่า

ขั้นตอนที่ 4: เลือกเวอร์ชันของคำสั่ง php ใน Command Line

คำสั่ง php ใน Terminal, Cronjob และ Composer ไม่ได้ใช้ FPM แต่ใช้ CLI ซึ่งเลือกผ่านระบบ alternatives:

# ดูตัวเลือกและเลือกแบบโต้ตอบ
sudo update-alternatives --config php

# หรือกำหนดตรง ๆ
sudo update-alternatives --set php /usr/bin/php8.2
php -v

ถ้าต้องการรันสคริปต์ด้วยเวอร์ชันเฉพาะโดยไม่เปลี่ยนค่า Default ให้เรียกไบนารีตรง ๆ เช่น php8.2 artisan migrate หรือ php8.3 /usr/local/bin/composer install วิธีนี้ปลอดภัยกว่าสำหรับ Cronjob ของแต่ละเว็บ เพราะไม่ขึ้นกับว่าใครเปลี่ยน alternatives ไปแล้ว

ตรวจสอบผลลัพธ์

สร้างไฟล์ทดสอบชั่วคราวในแต่ละเว็บ:

echo '<?php echo PHP_VERSION;' | sudo tee /var/www/legacy.example.com/public/v.php

เปิด http://legacy.example.com/v.php ควรเห็น 8.2.x และในเว็บใหม่ควรเห็น 8.3.x ตรวจเสร็จแล้วลบไฟล์ทิ้งทันที ไม่ควรเปิด phpinfo() ค้างไว้บนเว็บจริง เพราะเปิดเผยข้อมูลการตั้งค่าของเครื่อง

ดูว่า FPM ของเวอร์ชันใดมีการใช้งานได้จาก Log ของ Nginx หรือ Apache และจากจำนวนโปรเซส ps -C php-fpm8.2 -o pid,user,rss,cmd

ปัญหาที่พบบ่อย

หลังเพิ่ม PPA แล้ว PHP เดิมของระบบถูกอัปเกรด

PPA มีแพ็กเกจเวอร์ชันใหม่กว่าของ Ubuntu เช่น php8.3 บน 24.04 จะถูกแทนด้วยรุ่นย่อยจาก PPA นี่เป็นพฤติกรรมปกติ แต่ควรทดสอบเว็บหลังอัปเกรด และถ้าต้องการเลิกใช้ PPA ภายหลัง ใช้ ppa-purge เพื่อย้อนแพ็กเกจกลับเป็นของ Ubuntu

ติดตั้งแพ็กเกจแบบไม่ระบุเวอร์ชันแล้วได้ PHP ใหม่เพิ่มมา

คำสั่งอย่าง apt install php-mysql (ไม่มีเลข) จะดึงเวอร์ชัน Default ล่าสุดของ PPA มาด้วย ซึ่งอาจเป็นเวอร์ชันที่คุณไม่ต้องการ ให้ระบุเลขเวอร์ชันในชื่อแพ็กเกจเสมอ

Class not found หรือ Call to undefined function

ส่วนขยายติดตั้งแล้วแต่คนละเวอร์ชันกับที่เว็บใช้ ตรวจด้วย php8.2 -m ว่ามีโมดูลที่ต้องการหรือไม่ แล้วติดตั้งให้ตรงเวอร์ชัน เช่น sudo apt install php8.2-redis แล้วรีสตาร์ต php8.2-fpm

502 Bad Gateway หลังเปลี่ยนเวอร์ชัน

Path ของ Socket ไม่ตรงหรือ FPM เวอร์ชันนั้นยังไม่ทำงาน ตรวจ ls /run/php/ และ sudo journalctl -u php8.2-fpm -n 50

หากไม่แน่ใจว่าเว็บของคุณรองรับ PHP เวอร์ชันใด หรือย้ายเวอร์ชันแล้วเว็บทำงานผิดปกติ ติดต่อทีมซัพพอร์ต THAI DATA CLOUD ได้ที่ https://thaidata.cloud/contact/

ผู้ให้บริการคลาวด์ไทย
เพื่อธุรกิจของคนไทย

"มุ่งมั่น" และ "มั่นคง"
พร้อมรับมือทุกการเติบโต
Trust Cloud
คลาว์ที่ปลอดภัย
คือรากฐานที่มั่นคง
cloud security