PHP 不只能寫 Web,加上 Shebang #!/usr/bin/php -q 即可變身系統管理腳本。本文提供一支互動式選單腳本,支援建立虛擬主機(自動套用模板)、列出並刪除(含備份網站目錄與 Nginx 設定)、退出,適合中小型主機手動運維。
vhost.php#!/usr/bin/php -q
<?php
const SITES_ROOT = '/home/sites';
const NGINX_SITES = '/etc/nginx/sites';
const NGINX_TEMPLATE = '/etc/nginx/template/site_conf';
const BACKUP_DIR = '/etc/nginx/backup';
function menu() {
echo "=========== Vhost Manager ===========\n";
echo "= 1. Create 2. Delete 3. Exit =\n";
echo "=====================================\n";
echo "Choose: ";
return trim(fgets(STDIN));
}
function create() {
echo "Domain name: ";
$domain = trim(fgets(STDIN));
$path = SITES_ROOT . "/$domain";
$confFile = NGINX_SITES . "/$domain";
if (file_exists($path) || file_exists($confFile)) {
fwrite(STDERR, "Domain or config already exists!\n");
return;
}
mkdir($path, 0750, true);
$tpl = file_get_contents(NGINX_TEMPLATE);
// 模板變數替換:{$domain}, {$path}
eval("\$conf = \"$tpl\";"); // 注意:模板來源可信才可用 eval
file_put_contents($confFile, $conf);
echo "Created: $domain\n";
}
function delete() {
$dir = dir(NGINX_SITES);
$list = [];
while (($f = $dir->read()) !== false) {
if ($f !== '.' && $f !== '..' && is_file($dir->path . "/$f")) $list[] = $f;
}
if (!$list) { echo "No sites.\n"; return; }
foreach ($list as $i => $v) echo "$i. $v\n";
echo "Select number to delete: ";
$idx = (int)trim(fgets(STDIN));
if (!isset($list[$idx])) { echo "Invalid.\n"; return; }
$target = $list[$idx];
// 備份 Nginx 設定
copy(NGINX_SITES . "/$target", BACKUP_DIR . "/$target." . date('YmdHis'));
unlink(NGINX_SITES . "/$target");
// 打包網站目錄並刪除
exec("tar -czf " . SITES_ROOT . "/$target.tar.gz " . SITES_ROOT . "/$target");
exec("rm -rf " . SITES_ROOT . "/$target");
echo "Deleted & backed up: $target\n";
}
while (true) {
switch (menu()) {
case '1': create(); break;
case '2': delete(); break;
case '3': exit(0);
default: echo "Invalid option.\n";
}
}
/etc/nginx/template/site_confserver {
listen 80;
server_name {$domain};
access_log /var/log/nginx/{$domain}_access.log;
error_log /var/log/nginx/{$domain}_error.log;
root {$path};
location = /favicon.ico { log_not_found off; access_log off; }
location = /robots.txt { allow all; log_not_found off; access_log off; }
location / {
index index.html index.htm index.php;
try_files $uri $uri/ @proxy;
}
location ~* \.(html|htm)$ {
expires 30s; gzip off; add_header Content-Encoding gzip;
try_files $uri $uri/ /wp-content/cache/supercache/$http_host/$request_uri/index.html.gz @proxy;
}
location ~* \.(jpe?g|gif|png|ico|css|js|flv|swf|avi|zip|rar|svg|tgz|gz|bz2|doc|xls|exe|pdf|ppt|txt|tar|mp3)$ {
expires 30d;
}
location @proxy {
proxy_pass https://127.0.0.1:81;
include /etc/nginx/proxy.conf;
}
}
chmod +x vhost.php
sudo mv vhost.php /usr/local/bin/vhost
# 執行需 root 權限(寫 /etc/nginx、/home/sites)
sudo vhost
strtr($tpl, ['{$domain}'=>$domain, '{$path}'=>$path]) 或 preg_replace_callback。/^([a-z0-9-]+\.)+[a-z]{2,}$/i、防路徑穿越。exec('nginx -t && systemctl reload nginx')。listen 443 ssl、ssl_certificate、ssl_certificate_key,並整合 certbot --nginx 自動簽發。fastcgi_pass unix:/run/php/php8.2-fpm.sock; 可由參數決定。這支腳本展示了 PHP 做系統管理的表達力:熟悉語法、內建檔案/進程函式、易於維護擴充,比 Bash 更適合複雜邏輯。