W3docs

ftp_exec()

Aprende por qué ftp_exec() fue eliminado en PHP y cómo ejecutar comandos remotos de forma segura con la extensión ssh2 o phpseclib.

La función ftp_exec() de PHP

ftp_exec() era una función integrada de PHP que pedía a un servidor FTP remoto ejecutar un comando de shell en tu nombre. Fue declarada obsoleta en PHP 5.3.0 y eliminada en PHP 7.0.0, por lo que no está disponible en ninguna versión moderna de PHP. Esta página explica qué hacía, por qué desapareció y, lo más útil, cómo ejecutar comandos remotos de forma segura hoy en día.

Si solo necesitas gestionar archivos a través de FTP (subir, descargar, listar, renombrar), no necesitas ejecución de comandos en absoluto. Consulta la descripción general de PHP FTP y funciones como ftp_connect() y ftp_raw().

Qué hacía ftp_exec()

La función recibía dos parámetros y devolvía un boolean:

ParámetroTipoDescripción
$ftp_streamresourceLa conexión devuelta por ftp_connect().
$commandstringEl comando que se ejecuta en el servidor FTP.

Devolvía true si el servidor aceptaba y ejecutaba el comando, y false en caso de error. Internamente enviaba el comando FTP SITE EXEC, que solo funciona si el servidor habilita explícitamente esa característica.

Sintaxis histórica

bool ftp_exec(resource $ftp_stream, string $command)

La firma usaba un identificador de conexión de tipo resource. La clase orientada a objetos FTP\Connection se añadió en PHP 8.0, mucho después de que ftp_exec() ya hubiera sido eliminada, por lo que las dos nunca coexistieron.

Por qué fue eliminada

Dos problemas hicieron que ftp_exec() fuera inutilizable en la práctica:

  • Casi nunca estaba disponible. SITE EXEC permite que un cliente FTP ejecute comandos de shell arbitrarios en el servidor. Eso es un riesgo textbook de ejecución remota de código, por lo que servidores populares como vsftpd y ProFTPD la tienen deshabilitada de serie, y la mayoría de los proveedores nunca la activaron.
  • FTP en sí mismo es inseguro. El FTP plano envía las credenciales y los datos en texto claro. Añadir ejecución de comandos sobre un protocolo sin cifrar es exactamente la dirección equivocada. (Si debes usar FTP para archivos, prefiere ftp_ssl_connect() para FTPS.)

Como la funcionalidad era tanto peligrosa como efectivamente inutilizable, PHP la declaró obsoleta en 5.3.0 y la eliminó por completo en 7.0.0.

Advertencia

Llamar a ftp_exec() en PHP 7.0 o posterior lanza un Error: Call to undefined function ftp_exec(). No existe un reemplazo directo dentro de la extensión FTP — la ejecución de comandos remotos pertenece a SSH.

Ejecución segura de comandos remotos hoy en día

Para ejecutar un comando en una máquina remota desde PHP, usa SSH, no FTP. Existen dos opciones estándar:

  • La extensión ssh2 — una extensión nativa de PECL que envuelve libssh2.
  • phpseclib — una biblioteca en PHP puro que no necesita ninguna extensión, lo que la hace ideal en hosting compartido.

Opción 1: La extensión 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() abre el canal cifrado, ssh2_auth_password() inicia sesión y ssh2_exec() ejecuta el comando y devuelve un stream. Configurar el stream como bloqueante con stream_set_blocking() garantiza que leas la salida completa antes de que continúe el script — un error habitual que de otro modo produce resultados vacíos.

Opción 2: phpseclib (sin extensión necesaria)

<?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');

Dado que phpseclib está escrito completamente en PHP, funciona en cualquier lugar donde PHP esté disponible: sin compilación de PECL, sin extensión a nivel de servidor. Instálalo con composer require phpseclib/phpseclib.

Manejo de errores

Comprueba siempre el valor de retorno antes de leer la salida. Con la extensión ssh2, ssh2_exec() devuelve false en caso de error:

<?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);
}

Para mayor seguridad, prefiere la autenticación basada en clave (ssh2_auth_pubkey_file()) en lugar de contraseñas, y nunca interpolates entrada no confiable directamente en una cadena de comandos — escapa los argumentos con escapeshellarg() para evitar inyección de comandos.

Conclusiones clave

  • ftp_exec() ejecutaba un comando en un servidor FTP a través de SITE EXEC; fue declarada obsoleta en PHP 5.3.0 y eliminada en PHP 7.0.0.
  • Fue eliminada porque SITE EXEC es un riesgo de ejecución remota de código que la mayoría de los servidores deshabilitan, y FTP no está cifrado.
  • Para comandos remotos hoy en día, usa SSH a través de la extensión ssh2 o phpseclib — nunca FTP.
  • Para transferencias de archivos simples, la extensión FTP sigue siendo válida; comienza con ftp_connect(), ftp_login() y la descripción general de PHP FTP.

Práctica

Práctica
¿Cuál es el propósito del comando exec de FTP en PHP?
¿Cuál es el propósito del comando exec de FTP en PHP?
Was this page helpful?