ftp_exec()
Узнайте, почему PHP ftp_exec() устарела и удалена, и как запускать удалённые команды безопасно сегодня — через ssh2 или phpseclib.
Функция PHP ftp_exec()
ftp_exec() — встроенная функция PHP, которая просила удалённый FTP-сервер выполнить команду оболочки от вашего имени. Она была объявлена устаревшей в PHP 5.3.0 и удалена в PHP 7.0.0, поэтому недоступна ни в одной современной версии PHP. На этой странице объясняется, что она делала, почему исчезла и — что более важно — как сегодня безопасно запускать удалённые команды.
Если вам нужно только управлять файлами по FTP (загрузка, скачивание, просмотр, переименование), выполнение команд вам вовсе не требуется. Смотрите обзор PHP FTP и функции ftp_connect() и ftp_raw().
Что делала ftp_exec()
Функция принимала два параметра и возвращала boolean:
| Параметр | Тип | Описание |
|---|---|---|
$ftp_stream | resource | Соединение, возвращённое ftp_connect(). |
$command | string | Команда для выполнения на FTP-сервере. |
Она возвращала true, если сервер принял и выполнил команду, и false при ошибке. Под капотом функция отправляла FTP-команду SITE EXEC, которая работает только если сервер явно включил эту возможность.
Исторический синтаксис
bool ftp_exec(resource $ftp_stream, string $command)В сигнатуре использовался идентификатор соединения типа resource. Объектно-ориентированный класс FTP\Connection был добавлен в PHP 8.0 — уже после того, как ftp_exec() была удалена, — поэтому они никогда не сосуществовали.
Почему её удалили
Два недостатка делали ftp_exec() практически неприменимой:
- Она почти никогда не была доступна.
SITE EXECпозволяет FTP-клиенту выполнять произвольные команды оболочки на сервере. Это классический риск удалённого выполнения кода, поэтому основные серверы, такие как vsftpd и ProFTPD, поставляются с отключённой функцией, и большинство хостов её так и не включали. - FTP сам по себе небезопасен. Обычный FTP передаёт учётные данные и данные в открытом виде. Добавлять выполнение команд поверх незашифрованного протокола — заведомо неверное решение. (Если вам всё же нужен FTP для передачи файлов, предпочтите
ftp_ssl_connect()для FTPS.)
Поскольку функция была одновременно опасной и фактически мёртвой, PHP объявил её устаревшей в 5.3.0 и полностью удалил в 7.0.0.
Вызов ftp_exec() в PHP 7.0 и выше выбрасывает Error: Call to undefined function ftp_exec(). Прямой замены внутри FTP-расширения нет — удалённое выполнение команд относится к области SSH.
Безопасное удалённое выполнение команд сегодня
Для запуска команды на удалённой машине из PHP используйте SSH, а не FTP. Существуют два стандартных варианта:
- Расширение
ssh2— нативное PECL-расширение, обёртывающее libssh2. - phpseclib — библиотека на чистом PHP, не требующая расширений, что делает её идеальной для общего хостинга.
Вариант 1: расширение ssh2
<?php
// 1. Open an SSH connection (default SSH port is 22)
$conn = ssh2_connect('example.com', 22);
if (!$conn) {
die("Could not connect to server.\n");
}
// 2. Authenticate
if (!ssh2_auth_password($conn, 'username', 'password')) {
die("SSH authentication failed.\n");
}
// 3. Run the command
$stream = ssh2_exec($conn, 'ls -al');
if ($stream === false) {
die("Failed to execute command.\n");
}
// 4. Read its output
stream_set_blocking($stream, true);
$output = stream_get_contents($stream);
echo $output;ssh2_connect() открывает зашифрованный канал, ssh2_auth_password() выполняет вход, а ssh2_exec() запускает команду и возвращает поток. Установка потока в блокирующий режим с помощью stream_set_blocking() гарантирует, что вы прочитаете полный вывод до продолжения скрипта — типичная ловушка, которая в противном случае даёт пустые результаты.
Вариант 2: phpseclib (расширение не требуется)
<?php
require 'vendor/autoload.php';
use phpseclib3\Net\SSH2;
$ssh = new SSH2('example.com');
if (!$ssh->login('username', 'password')) {
exit('SSH login failed');
}
echo $ssh->exec('ls -al');Поскольку phpseclib написан полностью на PHP, он работает везде, где работает PHP — никаких сборок PECL, никаких расширений на уровне сервера. Установите его командой composer require phpseclib/phpseclib.
Обработка ошибок
Всегда проверяйте возвращаемое значение перед чтением вывода. С расширением ssh2 функция ssh2_exec() возвращает false при ошибке:
<?php
$stream = ssh2_exec($conn, 'ls -al');
if ($stream === false) {
echo "Failed to execute the command.\n";
} else {
stream_set_blocking($stream, true);
echo stream_get_contents($stream);
}Для большей надёжности предпочитайте аутентификацию по ключу (ssh2_auth_pubkey_file()) вместо паролей и никогда не подставляйте непроверенные данные напрямую в строку команды — экранируйте аргументы с помощью escapeshellarg(), чтобы избежать инъекции команд.
Основные выводы
ftp_exec()выполняла команду на FTP-сервере черезSITE EXEC; она была объявлена устаревшей в PHP 5.3.0 и удалена в PHP 7.0.0.- Удалена, потому что
SITE EXECпредставляет риск удалённого выполнения кода, большинство серверов отключают её, а FTP не шифруется. - Для удалённых команд сегодня используйте SSH через расширение
ssh2или phpseclib — но не FTP. - Для обычной передачи файлов FTP-расширение по-прежнему подходит; начните с
ftp_connect(),ftp_login()и обзора PHP FTP.