W3docs

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_streamresourceСоединение, возвращённое ftp_connect().
$commandstringКоманда для выполнения на 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.

Практика

Практика
Какова цель команды FTP exec в PHP?
Какова цель команды FTP exec в PHP?
Was this page helpful?