質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.59%

シェルスクリプトで、特定のリモートディレクトリ内へ、ファイルをFTP転送したい。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 881

umino

score 32

前提・実現したいこと

シェルスクリプトで確実に、特定のリモートディレクトリ内へ、ファイルをFTP転送したいです。

ローカルディレクトリにある1つのファイル(piyo.txt)を、
リモートディレクトリ(/home/remoteuser/tmp/niwatori/.)へftp転送したいです。

ftpコマンドはシェルスクリプト内でbatモード実行し、結果をログにリダイレクトします。
$ ftp -v -n < ftp_cmd.bat > ftp_cmd.result

↓ftpバッチファイルの中身

$ cat ftp_cmd.bat
open 192.168.123.123
username
passwd123
lcd /home/localuser/tmp/
mkdir /home/remoteuser/tmp/niwatori←★なかったときのため、リモートディレクトリniwatoriを作成する
cd /home/remoteuser/tmp/niwatori←★リモートディレクトリniwatoriに移動し
put piyo.txt←★目的のpiyo.txtをputする
bye

発生している問題・エラーメッセージ

しかし、ここで問題が発生しました。
上記の処理の場合、niwatoriディレクトリ作成に失敗した場合はcdできず、(同名のファイルniwatoriが存在する場合はmkdirできない)
リモートカレントにファイルをそのままputしてしまいます。

下記、(batファイルモードではありませんが)ftpコマンド失敗例↓

$ ftp
ftp> open 192.168.123.123
Connected to 192.168.123.123 (192.168.123.123).
220 (vsFTPd 3.0.3)
Name (192.168.123.123:localuser123): remoteuser123
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> 
ftp> cd tmp
250 Directory successfully changed.
ftp> 
ftp> mkdir niwatori
550 Create directory operation failed.←★同名のファイル"niwatori"が存在したので、550ステータスになってしまう
ftp> 
ftp> cd niwatori
550 Failed to change directory.←★niwatoriファイルが既存であり、ディレクトリを作成できなかったため、cdできず550ステータス
ftp> 
ftp> put piyo.txt
local: piyo.txt remote: piyo.txt←★cdに失敗したので、niwatoriディレクトリでなくカレントディレクトリにputしてしまっている
227 Entering Passive Mode (192,168,123,123,126,37).
150 Ok to send data.
226 Transfer complete.←★転送自体は成功の226ステータス
ftp> 
ftp> bye
221 Goodbye.


このような具合です。

●これからもできないこと
運用でカバーはできません。
最初からリモートにniwatoriディレクトリを作成したり、
niwatoriという名前のファイル作成を禁じることはできません。
batファイルを2つに分ける、ftpコマンド以外(sshなど)を使用もできません。

●できること
FTP実行結果ログ(ftp_cmd.result)をリダイレクトで取得していますので、
これを解析してシェルスクリプトでif判定することは可能です。(現状、そうする予定です。↓に続く

●いま考えている案
いまのところ、ftp結果ログをシェルスクリプト上でgrepなどで解析し、
「cdできたかどうか("550 Failed to change directory."の文言が存在したら、cdできなかったとして異常終了とする)」で判断するしかないかな??と思っています。

ログ解析よりスマートな方法をご存じの方、アイデアをお持ちの方、
どうかお知恵を貸していただけませんでしょうか。
よろしくお願いします。

補足情報(FW/ツールのバージョンなど)

CentOS7
bash

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • キャンセル

  • umino

    2020/02/19 18:41

    質問ありがとうございます。
    事情により、scpやsshオプションは使用できません。

    キャンセル

  • hoshi-takanori

    2020/02/19 18:44

    質問文中に書いてありましたね。失礼しました。bat ファイルというのは、純粋に ftp に食わせるコマンドを記述したもので、シェルスクリプトさえも使えないということでしょうか?

    キャンセル

  • umino

    2020/02/19 19:05

    hoshi-takanoriさん
    質問ありがとうございます。
    はい。batファイルというのは、ftp実行をバッチファイルモードで行うためだけのファイルです。

    1つのシェルスクリプト内ですべての処理(ftpコマンド組み立て、batファイル作成書き込み、ftp実行、ログ解析などすべて)を行っていますので、batファイルに何を書き込むかは、ある程度自由に決められます。
    なお、ftpをbatモードで行うのは事情があり、インタラクティブモードは使用できません。

    キャンセル

回答 2

checkベストアンサー

+1

ftpを使うならお書きの方針になるでしょう。

ftpにこだわらないなら、curlを使うと御心配のような中途半端な状況にはなりません。成功か、エラーで何もしないか、どちらか。

curl -u USER:PASS ftp://HOSTNAME/FOO/BAR/BAZ --ftp-create-dirs -T MYDIR/BAZ

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/02/19 22:21

    > 実行コマンドをすべて別途ログに出力する
    ああ、自分でログを作るということですね。
    案1:そこだけ書かない
    案2:コマンドラインに書かずファイルに書く

    キャンセル

  • 2020/02/20 18:08

    otnさん
    いろいろ考えてくださったようで、ありがとうございます。
    コマンドラインに書かずにファイルに書く、ですね。いま、その方向で実行しているので、このまま突っ切ろうと思いました。
    expectは読んだのですがわたしにはハードルが高く...もう少し実力が身についたら、ぜひ実践します。
    さまざまな角度からの考慮、感謝します。

    キャンセル

  • 2020/02/21 16:09

    curl -u $(cat password-file) ftp://HOSTNAME/FOO/BAR/BAZ --ftp-create-dirs -T MYDIR/BAZ
    が簡単でしょう。

    キャンセル

0

わたしなら、失敗する可能性のあるものと、失敗しないものと分けます。
ディレクトリを作成だけ行う処理と、ファイルを転送だけする処理にわけ、
無条件に2つの処理を行うことで、前者が失敗しても、後者は問題なく
処理を行うことができます。

ただ、もっと言うと、今時ftpではなくscpなりssh commandを利用した
処理に置き換えると思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/02/19 19:13

    わたしが勝手にbatファイルモードと読んでいた(そして、<で食わせるテキストファイルにに.bat拡張子をつけた)ことから余計にわかりづらくなってしまいました。
    正しくは、ftpコマンドに食わせるための、ftpコマンドを羅列したファイルのことです。(上記「ftp_cmd.bat」をご覧ください。)

    やりたいことは、niwatoriディレクトリが作成できてもできなくても(既にあっても)、piyo.txtをniwatoriディレクトリ内に送りたいのです。
    それを、1つのスクリプト内作成した1つのbatファイルで行いたいです。

    回答ありがとうございました。

    キャンセル

  • 2020/02/20 10:30

    > niwatoriディレクトリが作成できてもできなくても(既にあっても)、piyo.txtをniwatoriディレクトリ内に送りたい

    であれば、ログ解析などしなくても、最初に提示した通り、ディレクトリができてもできなくてもディレクトリを作るFTP処理のみ最初に行い、次のステップでファイルをputする処理をすれば良いかと。bashならftpコマンドを二回叩けば良いですし、コマンドファイルを作らなくてもヒアドキュメントを使えば良いです。

    キャンセル

  • 2020/02/20 18:11

    t_obaraさん
    追加の回答ありがとうございます。
    2つのファイルに分ける方法も、提案のひとつにいれることができました。
    (ヒアドキュメントでのトライは、ファイルと同じ構成で何度かやってみてftp正常終了できなかったのですが、実際は可能ということですので日を改めてトライしたいと思います。)
    わたしの知見を広げていただいたこと、感謝します。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る