ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

ゼロからはじめるPHP講座コミュのPHPを使ってのサーバ上ファイルのパーミッションの変更方法

  • mixiチェック
  • このエントリーをはてなブックマークに追加
PHPおよびPEARを使って、FTPサーバ上のファイルのパーミッションの変更をしたいと考えています。

具体的には、

PEARを利用し、$ftp->put()でアップしたファイル($filename)を、700に属性変更したいのです。

ソース上は、

chmod($filename, 0700);

と書いています。

ところが、実行すると以下のようなワーニングが出ます。

「Warning: chmod() [function.chmod]: No such file or directory in ・・・」

(もちろん該当ファイルはサーバ上に存在しています。)

今度は、

$ftp->chmod($remote_folder[$i]. $filename, 0700);

と書いて実行してみるとエラーは出ません。

しかし、パーミッションは変わっていませんでした。

次に、

「PEARの命令を使って実行すればいいんだ!」と考えて、

$ftp->execute(chmod($filename, 0700));

と書いて実行してみました。

結果は、最初と同じ、

「Warning: chmod() [function.chmod]: No such file or directory in ・・・」

というワーニングでした。

いったい何がいけないいんでしょうか(--;


phpのマニュアルを見ると、chmodに、「この関数では、 リモートファイルを使用することはできません。」とあります。

が、教えて!ネット上で検索してみると、chmodを使って普通にサーバ上のファイルのパーミッションを変更している書き込みが見られます。

正直、混乱しているというか、よく分からない状態です。


皆様、気がついた点などありましたら、是非、アドバイスお願い致します。

コメント(24)

No such file or directory
は、ディレクトリ・ファイルが存在しないというエラーです。
パスミスはありませんか?
ラスユキ Version 1.4さん

早速のご回答ありがとうございます。


>パスミスはありませんか?

パスミスはないと思います。

chmodの直前に、ファイル名およびパスをechoで表示して、正しいかどうかを確認していますので。


別のルートで、「$ftp->chmod($remote_folder[$i]. $filename, 0700); 」という(上記2番目の)書き方で正しい、というご指摘を頂きました。

そのため、これに修正することでエラーは無くなりました。

しかし、パーミッションはchmodで指定した値(777)変更されていませんでした。

エラーが出ない分、さらに厄介になっってしまったような・・・

引き続きご指摘などアドバイスお待ちしております。
せっかく答えたのにマルチとはどういうおつもりでしょうか?
http://mixi.jp/view_bbs.pl?id=28916760&comment_count=0&comm_id=650
すみません。

不快に思われてしまったようですね。

とにかく焦ってしまっていて・・・こうしたことをしてしまいました。

ラスユキ Version 1.4さん、良いご回答があれば、引き続き対応くださるとうれしいです。
chmod($filename, 0700);

この変数($filename)の値を記載できませんか?
一部マスクでも構いません。

$ftp->chmod($remote_folder[$i]. $filename, 0700);
こっちは「$remote_folder[$i]. $filename」こう書いているのも
気になります。
> $ftp->execute(chmod($filename, 0700));

chmod()はローカル(PHPが動いているWebサーバー上)のファイルのパーミッションを変更するものですから
ftpサーバー上のファイルのパーミッションを変更するなら、

$ftp->execute("chmod 0700 $filename");

ではないですか?

それと、匿名ftpサーバーなど一部のftpサーバーでは、chmodを禁止している場合があります。
(コマンドラインのftpコマンドを使ってみるなりして、エラーが出ないかで実験してみてはどうでしょう)
YamaHiroさん
コメントありがとうございます。


>この変数($filename)の値を記載できませんか?

値は、具体的には「config.cgi」です。
ローカル(自分のパソコン)上にある特定のフォルダから、opendir、readdirで読み込んでいます。


>$ftp->chmod($remote_folder[$i]. $filename, 0700);
>こっちは「$remote_folder[$i]. $filename」こう書いているのも
>気になります。

スミマセン。
私の記載ミスです。
読む側に分かりやすくするために、$filenameのみを記載しようと思っていました。
ですが、ここだけ、(書くつもりのなかった)不要な『$remote_folder[$i]. 』も転載してしまいました。
ごめんなさい
ファイル名のご回答頂きましたが、
SAGさんのご回答で解決しますよね。
あ、いえいえ。横レスしてすいませんでした。

$ftp->chmod(); や $ftp->execute(); する前に、$ftp->cd( ); しているかどうか次第かと思いますが、
それの明示がないので、ほんとにftpサーバー上のファイル名を正しく指定しているのか
という、ご指摘は、ごもっともだと思います。


> しかし、パーミッションはchmodで指定した値(777)変更されていませんでした。

タイプミスだと思いますが、chmod で0700を指定したのなら、
期待される結果は、777ではなく、700ですよね。
それとも、"chmod"の仕様を勘違いされているとか。
SAGさん
コメントありがとうございます。


>$ftp->execute("chmod 0700 $filename");
>ではないですか?

先ほどまで、PHPのftp_ite()関数を使ってchmodの変更を試みていました。
具体的に書くと、「ftp_site($ftp, "chmod 0700 $filename");」です。
が、「Warning: ftp_site() expects parameter 1 to be resource, object given ・・・」というエラーが出てうまくいきませんでした。

SAGさんのご指摘の通りにコーディングしてみると、エラーが出ず、うまくいきました。

しかし・・・パーミッションは700に変更されず、元の644のままでした。


>それと、匿名ftpサーバーなど一部のftpサーバーでは、chmodを禁止している場合があります。
>(コマンドラインのftpコマンドを使ってみるなりして、エラーが出ないかで実験してみてはどうでしょう)

はい。
それもやってみたいと思います。
実行後、またカキコします。
SAGさん

>$ftp->chmod(); や $ftp->execute(); する前に、$ftp->cd( ); しているかどうか次第かと思いますが、
>それの明示がないので、ほんとにftpサーバー上のファイル名を正しく指定しているのか
>という、ご指摘は、ごもっともだと思います。

はい、そのとおりですね。
実際は、$ftp->cd( )でターゲットディレクトリに移動し、chmodを実行しています。
echo($ftp->pwd());で移動が正しく行われたかの確認も行っています。


>タイプミスだと思いますが、chmod で0700を指定したのなら、
>期待される結果は、777ではなく、700ですよね。

たしかに・・・。
タイプミスです。
現状が644になっていて、それを700に変えようとしています。

混乱させてスミマセンでした。
> 「ftp_site($ftp, "chmod 0700 $filename");」です。

> 「Warning: ftp_site() expects parameter 1 to be resource, object given ・・・」

ftp_site()つかうなら、引数に$ftpを渡してはだめですね。

事前に、
$conn = ftp_connect(サーバー名);
ftp_login($conn, ユーザー名, パスワード);
ftp_cd ( $conn, パス名);
しておいた、$conn を渡す必要があります。
(別に、$connでなくても、名前はなんでもいいのですが)

なお、そこまでやるなら、ftp_site(); よりも、 ftp_chmod($conn, 0700, $filename);
のほうが、ftpサーバーのコマンド仕様の違いを吸収してくれるかもしれません。


> しかし・・・パーミッションは700に変更されず、元の644のままでした。

WindowsベースのFTPサーバーにありがちなんですが、 (とくにSMBサーバー兼用型のNASとか)
chmod をエラーもなく受け付けるけど、無視するというケースもありえますね。
これに該当するかどうかも、手動ftpで、chmod してls してみればはっきりすると思います。
SAGさん

>それと、匿名ftpサーバーなど一部のftpサーバーでは、chmodを禁止している場合があります。
>(コマンドラインのftpコマンドを使ってみるなりして、エラーが出ないかで実験してみてはどうでしょう)

>WindowsベースのFTPサーバーにありがちなんですが、 (とくにSMBサーバー兼用型のNASとか)
>chmod をエラーもなく受け付けるけど、無視するというケースもありえますね。
>これに該当するかどうかも、手動ftpで、chmod してls してみればはっきりすると思います。


ローカル(自分のパソコン)からコマンドプロンプトを立ち上げ、ftp接続してみました。

ここでターゲットディレクトリまで移動し、「site chmod 0700 config.cgi」とコマンドを打つと、「Invalid command.」とエラーが出ました。

lsなど、他のコマンドではエラーが出ません。

ということは、当該のFTPサーバは、「chmodを禁止している」と考えるのがいいということでしょうか。


で、ひとつ気になることがあります。

FTPコマンドを打てる『SmartFTP』というツールがありまして、そこから「site chmod 0700 config.cgi」と打つと、正常にパーミッションが変更されます。

これは何故なのか、疑問に思うところです。
SmartFTPを知らないのですが、多分そのツールがftpサイト毎のコマンド体系の違いを吸収しているのfではないでしょうか。

ただし、chmod機能自体は受け付けているftpサーバーのようなので、期待がもてますね。


コマンドラインのftp で
chmod 700 config.cgi
site chmod 700 config.cgi
quote site chmod 700 config.cgi
のどれが成功するかを確認してみて下さい。

成功したら、それを
$ftp->execute("成功したコマンド パーミッション値 ファイル名");
で指定するとよいのではないかと思います。


ただし、そういう書き方をすると、移植性が低くなるので、
別経路として、pearのクラスでなく、PHPの関数のftp_chmod();のほうで
でできないかも、トライしたほうがよいように個人的には思います。
SAGさん
毎度毎度ありがとうございます。

「site chmod 700 config.cgi」で成功したので、このコマンドを貼り付けてやってみました。

コードとしては、
$ftp->execute("site chmod 0700 ファイル名");
です。

実行してみると、connect、login、cd、putまではうまくいくのですが、上記処理は駄目でした。
(パーミッションは644のまま。)


SAGさんに教えていただいた内容をヒントに、このFTPサーバのホスティング業者(stepサーバです)に問い合わせてみました。

すると次のような返答が帰ってきました。

「ステップサーバーのPHPはセーフモードにて動作していますので、
一部関数に制限が掛かっています。
セーフモードの制限内容については、下記ページよりご確認頂きま
すようお願い致します。
セーフモードにより制限を受けるか無効となる関数
http://jp.php.net/manual/ja/features.safe-mode.functions.php
なお、SITE CHMOD については対応しておりますので、FTPにてパ
ーミッション変更は可能です。」

要は、「chmod関数もセーフモードの制限を受ける」ということですね。

『どういう制限を受けるか』ですが、上記リンクにはこう書いてあります。
「処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。」
自分なりにこの意味を訳すと、
『サーバ上に実行プログラムを置かないと、chmodを行うことは無理』
ということですかね・・・
$ftp->execute("site chmod 0700 ファイル名");
でなく
$ftp->execute("site chmod 700 ファイル名");
では、どうですか?


ところで、ftpサーバー側での、PHPがセーフモード云々の件ですが、
なぜリモートのFTPサーバーで動いているPHPの仕様が、ローカルのPHPの動作に関係するのか理解できないのですが、もしかしてPHPから自分自身にFTPしているのですか?
(それとも、別々のホストだけど、同一仕様のサーバー間でftpしているってことですか?)

なお、ftpのchmodコマンド (リモートのftpサーバー上のファイルのパーミッション)と 、
phpのchmod() 関数(phpが動作しているローカルサーバー上のファイルのパーミッション)は
別ものなので、整理しなおしてみてはどうでしょう。


SAGさん

$ftp->execute("site chmod 700 ファイル名"); でも結果は変わりませんでした(--;。


>なぜリモートのFTPサーバーで動いているPHPの仕様が、ローカルのPHPの動作に関係するのか
>理解できないのですが、もしかしてPHPから自分自身にFTPしているのですか?
>(それとも、別々のホストだけど、同一仕様のサーバー間でftpしているってことですか?)

今つくっているプログラムの流れを説明します。

ローカル(デスクトップ上のパソコン:WinXP)上でPHPプログラムは動いています。
(これをaction.phpとします。)
このaction.phpには、
1.インターネット上のFTPサーバにconnect、loginし、
2.ターゲットディレクトリにcdし、
3.ローカル(デスクトップ上のパソコン:WinXP)上にあるファイルをputし、
4.そのファイルに対してchmodする、
というソースが書かれています。

つまり、ローカルで動くプログラムが、インターネット(リモート?)にあるFTPサーバ上のファイルにchmodする、というわけです。

(この説明で分かりましたでしょうか^^;)


>なお、ftpのchmodコマンド (リモートのftpサーバー上のファイルのパーミッション)と 、
>phpのchmod() 関数(phpが動作しているローカルサーバー上のファイルのパーミッション)は
>別ものなので、整理しなおしてみてはどうでしょう。

そうなのですか・・・
分かりました。
そうしてみますね。
ありがとうございます。
> $ftp->execute("site chmod 700 ファイル名"); でも結果は変わりませんでした(--;。

あれれ。そうですか。
もしかして、ファイル名はそのまま”ファイル名”って書いちゃってます?
$filename
なり
config.cgi
なりにプログラムの前後に合わせての書き換えが必要ですけど。


それと、ローカルとFTPの環境の件ですが、そうなると、
ホスティング業者(stepサーバ)のPHPはこの処理には使っていないってことですよね?
それなら、向こう側のPHPの仕様は関係ないですよ。

SAGさん

>あれれ。そうですか。
>もしかして、ファイル名はそのまま”ファイル名”って書いちゃってます?

ひえ〜(泣) そこまで心配されていたとは(笑)。
キチンと修正しておりますのでご安心を。


>ホスティング業者(stepサーバ)のPHPはこの処理には使っていないってことですよね?

はい。
使っていません。

>それなら、向こう側のPHPの仕様は関係ないですよ。

そうですか。
ご指摘ありがとうございます。

何か・・・あと一歩のような気がします。
頑張ります。
皆様・・・解決しました!


正常動作したソースは、「$ftp->chmod($filenameファイル名, 700);」です。


原因なのですが、「PEARのchmodが実行されていた」からでした(多分)。


この説明では分からないかもしれないので、説明しますと・・・

これまで私は、PHPのchmod・ftp_chmodや、SITEコマンド&PEARのexecuteなどを使って、パーミッションの変更を行おうとしていました。

全くうまくいきませんでした。

本日、ふとPEARのFTP.phpのソースを確認してみました。

すると、何と!PEARにもchmodというそのままの名前のfunctionがあるではありませんか!

しかも、このPEARのchmodは、引数が(ファイル名 , 属性値)という順番だったのです。

そこで試しに、(上記した)「$ftp->chmod($filenameファイル名, 700);」を書いて実行してみました。

うまくいきましたわーい(嬉しい顔)。

ちなみに、PEARのchmodは、(PEARの)マニュアルには一切書かれていません。

FTP.phpのソースを見て初めて発見できたことでした。


フーッ。

この一週間、これだけに時間をとられていましたが、ようやっと解決しました。

ご回答いただいた方々、そしてSAGさん、ありがとうございました。
えっと。なんだか、現象がよくわかりませんが、解決されてよかったですね。

$ftp->chmod() は$ftpをどう作ったかに依存しますが、そのクラスのメソッドで
ftp_chmod() は、PHPのFTP用の関数で、
chmod() は PHPのローカルファイル用の関数で、
それからを、ごちゃまでに理解していたってことなんですかね。


なお、成功されたという記述は最初に

> $ftp->chmod($remote_folder[$i]. $filename, 0700);
> と書いて実行してみるとエラーは出ません。
> しかし、パーミッションは変わっていませんでした。

ということでしたが、この時点で、ファイルのパス(FTPサーバー側でのパス指定)を
間違えていただけで、$ftp->chmod( ) の使い方自体は正しかったってことなんだと思います。
(引数の順番もあってますし)
SAGさん

>$ftp->chmod() は$ftpをどう作ったかに依存しますが、そのクラスのメソッドで
>ftp_chmod() は、PHPのFTP用の関数で、
>chmod() は PHPのローカルファイル用の関数で、
>それからを、ごちゃまでに理解していたってことなんですかね。

はい、はじめのころは確かに、そうした違いさえ知りませんでした。

ですが、今回の根本的な原因は、
「PHPのchmodよりも先に、PEARのchmodが実行されていたから」
ということだったと認識しています。
(あくまで自分なりの理解ですが。)


>> $ftp->chmod($remote_folder[$i]. $filename, 0700);
>> と書いて実行してみるとエラーは出ません。
>> しかし、パーミッションは変わっていませんでした。
>ということでしたが、この時点で、ファイルのパス(FTPサーバー側でのパス指定)を
>間違えていただけで、$ftp->chmod( ) の使い方自体は正しかったってことなんだと思います。

この時点では、「エラーは出ません」とか言いながら、エラーの取得の処理を入れていなかったというお粗末なこともやっていました。
(だからエラーも出なかった。)
この部分をしっかりしていれば、解決はもっと早かったかもしれませんね。
いろいろとお手数おかけしましたあせあせ。

ログインすると、残り2件のコメントが見れるよ

mixiユーザー
ログインしてコメントしよう!

ゼロからはじめるPHP講座 更新情報

ゼロからはじめるPHP講座のメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング