この記事では、PHPでSSHやSFTPを利用するためのライブラリphpseclib 3.0の使い方を解説します。
phpseclibのインストール
phpseclibは、PHPのライブラリ管理ツールComposerを使ってインストールします。まだComposerを導入していないならば、下記の記事を参考にインストールしてください。
ターミナルでプロジェクトのディレクトリに移動し、以下のコマンドを実行するとphpseclibがインストールされます。
composer require phpseclib/phpseclib
PHPスクリプトに以下の記述をすると、phpseclibを使用するために必要なファイルが読み込まれます。
require_once 'vendor/autoload.php';
これで、phpseclibを利用する準備が整いました。
SSH2
認証
SSHでサーバにログインするとき、パスワード認証と公開鍵認証の2つの認証方法があります。以下では、それぞれの認証方法について解説します。ちなみに、公開鍵認証のほうがセキュリティが高いとされています。
パスワード認証
パスワード認証は、ユーザ名とパスワードを使って認証を行う方法です。以下は、phpseclibでパスワード認証を使ってSSH接続をする場合のコードです。
use phpseclib3\Net\SSH2;
//接続先の情報を設定
$host = 'example.com';
$username = 'username';
$password = 'password';
//SSH2の接続を試行
$ssh = new SSH2($host);
if (!$ssh->login($username, $password)) {
exit('ログイン失敗');
}
//コマンドを実行
echo $ssh->exec('ls -la');
公開鍵認証
公開鍵認証は、公開鍵と秘密鍵を使って認証を行う方法です。以下は、phpseclibで公開鍵認証を使ってSSH接続をする場合のコードです。まずは、鍵にパスフレーズを設定していない場合の例です。
use phpseclib3\Net\SSH2;
use phpseclib3\Crypt\PublicKeyLoader;
//接続先の情報を設定
$host = 'example.com';
$username = 'username';
//秘密鍵
$key = PublicKeyLoader::load(file_get_contents('/path/to/privatekey'));
//SSH2の接続を試行
$ssh = new SSH2($host);
if (!$ssh->login($username, $key)) {
exit('ログイン失敗');
}
//コマンドを実行
echo $ssh->exec('ls -la');
9行目で秘密鍵を読み込んでいます。秘密鍵はデフォルトの設定ならば~/.ssh/id_rsa
にあります。そして13行目でパスワードの代わりに秘密鍵を渡します。
鍵を作成するときにパスフレーズを設定している場合は次のようになります。
use phpseclib3\Net\SSH2;
use phpseclib3\Crypt\PublicKeyLoader;
//接続先の情報を設定
$host = 'example.com';
$username = 'username';
$passphrase = 'passphrase';
//秘密鍵
$key = PublicKeyLoader::load(file_get_contents('/path/to/privatekey'), $passphrase);
//SSH2の接続を試行
$ssh = new SSH2($host);
if (!$ssh->login($username, $key)) {
exit('ログイン失敗');
}
//コマンドを実行
echo $ssh->exec('ls -la');
10行目、秘密鍵を読み込むときにパスフレーズを渡します。それ以外はパスフレーズ無しと同じです。
コマンドの実行
単発コマンド
SSHで接続して、サーバでコマンドを実行するにはexec()
メソッドを使います。
//コマンドを実行
echo $ssh->exec('ls -la');
exec()
は、デフォルトではstdout
とstderr
の両方を返します。つまり、コマンドの実行に成功すればその結果を返すし、失敗すればエラーメッセージを返します。
//存在しないコマンドを実行
echo $ssh->exec('ls-la');
/*出力 エラーメッセージが返る
ls-al: Command not found.
*/
stderr
を出力したくない場合は$ssh->enableQuietMode()
を使います。設定を戻すときは$ssh->disableQuietMode()
です。
//stderrを制御
$ssh->enableQuietMode();
//存在しないコマンドを実行
echo $ssh->exec('ls-la');
/*出力 エラーメッセージは返らない
*/
終了ステータスを取得するにはgetExitStatus()
を使います。
//stderrを制御
$ssh->enableQuietMode();
//コマンドを実行
echo $ssh->exec('ls-al');
//エラーの場合
if ($ssh->getExitStatus()) {
echo 'エラーだっちゃ';
}
終了ステータスは、一般的には成功時に0
、失敗時に1
となります。
対話型コマンド
対話型のコマンドを実行する場合は、read()
およびwrite()
メソッドを使います。
echo $ssh->read('username@server:~ %');
$ssh->write("rm -i file.txt\n");
echo $ssh->read('remove file.txt?');
$ssh->write("y\n");
まず1行目、read()
メソッドでシェルのプロンプトを読みます。これ、忘れずにやってください。2行目でコマンドを書き込みます。"\n"
で改行するのを忘れないでください。3行目でremove file.txt?
を読んで、4行目でy
を書いてenterします。
無料で利用できるプログラミング学習サービスをお探しならば Code Lesson はいかがでしょうか。プロのエンジニアが監修した学習ロードマップで効率的に学習、AIに質問、最後にクイズで理解度をチェックできます。
SFTP
SFTPとは、SSHによる暗号化通信を利用したFTPのことです。通常のFTPと同じように、ファイルのアップロードやダウンロード、ディレクトリの作成、削除、移動、ファイルの一覧表示などができます。
認証
SFTPは、SSHと同じようにパスワード認証と公開鍵認証の2つの認証方法があります。
パスワード認証
以下は、phpseclibでパスワード認証を使ってSFTP接続をする場合のコードです。
use phpseclib3\Net\SFTP;
//接続先の情報を設定
$host = 'example.com';
$username = 'username';
$password = 'password';
//SFTPの接続を試行
$sftp = new SFTP($host);
if (!$sftp->login($username, $password)) {
exit('ログイン失敗');
}
公開鍵認証
以下は、phpseclibで公開鍵認証を使ってSFTP接続をする場合のコードです。
use phpseclib3\Net\SFTP;
use phpseclib3\Crypt\PublicKeyLoader;
//接続先の情報を設定
$host = 'example.com';
$username = 'username';
$passphrase = 'passphrase';
//秘密鍵
$key = PublicKeyLoader::load(file_get_contents('/path/to/privatekey'), $passphrase);
//SFTPの接続を試行
$sftp = new SFTP($host);
if (!$sftp->login($username, $key)) {
exit('ログイン失敗');
}
上記はパスフレーズありの例です。パスフレーズなしの場合は10行目の$passphrase
は指定しなくてOKです。
ファイルのアップロード
phpseclibでファイルをアップロードするにはput()
メソッドを使います。
//転送するファイルの情報
$remote_file = '/path/to/remote/file';
$local_file = '/path/to/local/file';
//ファイルのアップロード
if (!$sftp->put($remote_file, $local_file, SFTP::SOURCE_LOCAL_FILE)) {
exit('アップロード失敗');
}
これで、$local_file
から$remote_file
にファイルがアップロードされます。リモートファイルがすでに存在する場合は上書きされるのでご注意ください。
put()
の3つめの引数SFTP::SOURCE_LOCAL_FILE
は、ローカルファイルをアップロードすることを表しています。これをSFTP::SOURCE_STRING
にすると、文字列をリモートファイルに書き込むモードになります。
//転送するファイルの情報
$remote_file = '/path/to/remote/file';
$string = '文字列';
//文字列の書き込み
if (!$sftp->put($remote_file, $string, SFTP::SOURCE_STRING)) {
exit('書き込み失敗');
}
これで、文字列がリモートファイルに書き込まれます。なお、第3引数の初期値はSFTP::SOURCE_STRING
なので、省略して$sftp->put($remote_file, $string)
と書いてもOKです。
ファイルのダウンロード
phpseclibでファイルをアップロードするにはget()
メソッドを使います。
//転送するファイルの情報
$remote_file = '/path/to/remote/file';
$local_file = '/path/to/local/file';
//ファイルのダウンロード
if (!$sftp->get($remote_file, $local_file)) {
exit('ダウンロード失敗');
}
第2引数(ローカルファイル)を指定しなければ、リモートファイルの内容を返します。
//転送するファイルの情報
$remote_file = '/path/to/remote/file';
//ファイルの内容を表示
echo $sftp->get($remote_file);
ディレクトリの操作
phpseclibでディレクトリの作成、削除、移動などをするには、以下のメソッドを使います。
$sftp->mkdir('dir'); //dirという名前のディレクトリを作成する
$sftp->rmdir('dir'); //ディレクトリを削除する 中にファイルがあったら削除できない
$sftp->delete('dir'); //ディレクトリを削除する 中にファイルがあったらすべて削除する
$sftp->chdir('dir'); //dirという名前のディレクトリに移動する
echo $sftp->pwd(); //カレントディレクトリの絶対パスを表示する
mkdir()
メソッドは、PHPのmkdir()関数と同じパラメータを受け入れます。なので、2つ目のパラメータでパーミッションを指定することができます。指定しない場合はOS標準のパーミッション(umask)になります。
ファイルの一覧情報
ディレクトリ内のファイル一覧を取得するメソッドは2つあります。
//ファイル名の一覧を取得する
print_r($sftp->nlist());
/*出力
Array
(
[0] => .
[1] => ..
[2] => index.html
[3] => images
[4] => file.txt
[5] => file2.txt
)
*/
//ファイルの一覧と詳細な情報を取得する
print_r($sftp->rawlist());
/*出力
Array
(
[.] => Array
(
[size] => 512
[uid] => 0
[gid] => 1000
[mode] => 16877
[type] => 2
[atime] => 1683650342
[mtime] => 1683650650
[filename] => .
)
[..] => Array
(
[size] => 512
[uid] => 1000
[gid] => 1000
[mode] => 16837
[type] => 2
[atime] => 1601228067
[mtime] => 1683650354
[filename] => ..
)
[index.html] => Array
(
[size] => 6927
[uid] => 1000
[gid] => 1000
[mode] => 33188
[type] => 1
[atime] => 1683650415
[mtime] => 1683650415
[filename] => index.html
)
[images] => Array
(
[size] => 512
[uid] => 1000
[gid] => 1000
[mode] => 16877
[type] => 2
[atime] => 1683650436
[mtime] => 1683650868
[filename] => images
)
[file.txt] => Array
(
[size] => 25415
[uid] => 1000
[gid] => 1000
[mode] => 33188
[type] => 1
[atime] => 1683650547
[mtime] => 1683650533
[filename] => file.txt
)
[file2.txt] => Array
(
[size] => 8
[uid] => 1000
[gid] => 1000
[mode] => 41453
[type] => 3
[atime] => 1683650649
[mtime] => 1683650649
[filename] => file2.txt
)
)
*/
これらのメソッドは、第1引数にディレクトリ名を指定すると、そのディレクトリ内の情報を返します。また、第2引数にtrue
を指定すると、サブディレクトリの情報も返します。
ファイルの一覧情報は、デフォルトではソートされません。setListOrder()
メソッドで、一覧の順序を制御することができます。なお、ソートした場合は常にディレクトリが先、ファイルが後という順序になります。
//ファイル名で昇順にソート
$sftp->setListOrder('filename', SORT_ASC);
//サイズで降順にソートし、ファイル名で昇順にソート
$sftp->setListOrder('size', SORT_DESC, 'filename', SORT_ASC);
ファイルの操作
phpseclibでファイルの作成、削除、変更などをするには、以下のメソッドを使います。
$sftp->touch('file'); //fileという名前のファイルを作成する 同じ名前のファイルがあれば上書きする
$sftp->delete('file'); //ファイルを削除する
$sftp->rename('file', 'newname'); //ファイルの名前を変更する
$sftp->chmod(0600, 'file'); //ファイルのパーミッションを600にする
$sftp->chown('file', 1000); //ファイルのUIDを1000にする
$sftp->chgrp('file', 1000); //ファイルのGIDを1000にする
$sftp->truncate('file', 1024); //ファイルのサイズを1024バイトに切り詰める
ファイルの情報
phpseclibで、特定のファイルの情報を取得するにはstat()
メソッドを使います。
print_r($sftp->stat('file'));
/*出力
Array
(
[size] => 6927
[uid] => 0
[gid] => 1000
[mode] => 33188
[type] => 1
[atime] => 1683660384
[mtime] => 1683650415
)
*/
ファイルがシンボリックリンクの場合、stat()
メソッドはリンク先の実体の情報を返します。シンボリックリンクそのものの情報を取得したい場合はlstat()
を使います。
ファイルの情報を個別に取得するメソッドもあります。
$sftp->filesize('file');
$sftp->fileowner('file');
$sftp->filegroup('file');
$sftp->fileperms('file');
$sftp->filetype('file');
$sftp->fileatime('file');
$sftp->filemtime('file');
さいごに
というわけで、phpseclibの使い方を解説しました。PHP公式のSSH2 extensionもあるのですが、レンタルサーバーなどではインストールされていないことがあるので、そんなときはphpseclibのお世話になりましょう。
でわでわ
プログラミングの独学に行き詰まっていませんか?誰かに相談したい、もっと効率よく学びたいなら、プログラミングスクールを検討してみてください。
コメント