ftp_exec()
Learn why PHP's ftp_exec() was deprecated and removed, and how to run remote commands securely today with the ssh2 extension or phpseclib.
The PHP ftp_exec() Function
ftp_exec() was a built-in PHP function that asked a remote FTP server to run a shell command on your behalf. It was deprecated in PHP 5.3.0 and removed in PHP 7.0.0, so it is unavailable in any modern PHP version. This page explains what it did, why it disappeared, and — more usefully — how to run remote commands safely today.
If you only need to manage files over FTP (upload, download, list, rename), you do not need command execution at all. See the PHP FTP overview and functions like ftp_connect() and ftp_raw().
What ftp_exec() Did
The function took two parameters and returned a boolean:
| Parameter | Type | Description |
|---|---|---|
$ftp_stream | resource | The connection returned by ftp_connect(). |
$command | string | The command to run on the FTP server. |
It returned true if the server accepted and ran the command, and false on failure. Under the hood it sent the FTP SITE EXEC command, which only works if the server explicitly enables that feature.
Historical Syntax
bool ftp_exec(resource $ftp_stream, string $command)The signature used a resource connection identifier. The object-oriented FTP\Connection class was added in PHP 8.0 — long after ftp_exec() had already been removed — so the two never coexisted.
Why It Was Removed
Two problems made ftp_exec() unusable in practice:
- It was almost never available.
SITE EXEClets an FTP client run arbitrary shell commands on the server. That is a textbook remote-code-execution risk, so mainstream servers such as vsftpd and ProFTPD ship with it disabled, and most hosts never turned it on. - FTP itself is insecure. Plain FTP sends credentials and data in clear text. Layering command execution on top of an unencrypted protocol is exactly the wrong direction. (If you must use FTP for files, prefer
ftp_ssl_connect()for FTPS.)
Because the feature was both dangerous and effectively dead, PHP deprecated it in 5.3.0 and dropped it entirely in 7.0.0.
Calling ftp_exec() in PHP 7.0 or later throws an Error: Call to undefined function ftp_exec(). There is no drop-in replacement inside the FTP extension — remote command execution belongs to SSH.
Secure Remote Command Execution Today
To run a command on a remote machine from PHP, use SSH, not FTP. Two standard options exist:
- The
ssh2extension — a native PECL extension wrapping libssh2. - phpseclib — a pure-PHP library that needs no extension, which makes it ideal on shared hosting.
Option 1: The ssh2 Extension
<?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() opens the encrypted channel, ssh2_auth_password() logs in, and ssh2_exec() runs the command and returns a stream. Setting the stream to blocking with stream_set_blocking() guarantees you read the full output before the script continues — a common gotcha that otherwise yields empty results.
Option 2: phpseclib (No Extension Required)
<?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');Because phpseclib is written entirely in PHP, it runs anywhere PHP does — no PECL build, no server-level extension. Install it with composer require phpseclib/phpseclib.
Handling Errors
Always check the return value before reading output. With the ssh2 extension, ssh2_exec() returns false on failure:
<?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);
}For stronger guarantees, prefer key-based authentication (ssh2_auth_pubkey_file()) over passwords, and never interpolate untrusted input directly into a command string — escape arguments with escapeshellarg() to avoid command injection.
Key Takeaways
ftp_exec()ran a command on an FTP server viaSITE EXEC; it was deprecated in PHP 5.3.0 and removed in PHP 7.0.0.- It was removed because
SITE EXECis a remote-code-execution risk that most servers disable, and FTP is unencrypted. - For remote commands today, use SSH through the
ssh2extension or phpseclib — never FTP. - For plain file transfers, the FTP extension is still fine; start with
ftp_connect(),ftp_login(), and the PHP FTP overview.