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

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

新規登録して質問してみよう
ただいま回答率
85.37%
bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

シェル

シェル(shell)はUnix や Linux 系のOSで使用されるコマンドインタプリタを指します。

Q&A

解決済

2回答

3860閲覧

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

umino

総合スコア54

bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

シェル

シェル(shell)はUnix や Linux 系のOSで使用されるコマンドインタプリタを指します。

0グッド

0クリップ

投稿2020/02/19 09:18

編集2020/02/19 09:33

前提・実現したいこと

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

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

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

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

console

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

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

しかし、ここで問題が発生しました。
上記の処理の場合、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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

umino

2020/02/19 09:41

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

2020/02/19 09:44

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

2020/02/19 10:05

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

回答2

0

ベストアンサー

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

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

sh

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

投稿2020/02/19 09:51

otn

総合スコア85764

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

umino

2020/02/19 10:18

otnさん さっそくのご回答、ありがとうございます。 なるほど、そのようなやりかたもできるのですね。 実行コマンドをすべて別途ログに出力する必要があるのですが、curlだとパスワード平文がログに残ってしまうため、おとなしくログファイル解析をしようと思います。 (.batファイルを使用するまどろっこしい方法も、パスワードをログに残せないという背景から生まれました。) 太鼓判を押していただいて、安心して実装できます。 ご回答に感謝します。
otn

2020/02/19 11:05

? ftpサーバー側のログだと、どのクライアントでも同じだと思いますが、どこのログの話ですかね?
otn

2020/02/19 11:36

あとは、ftpにリダイレクトでサブコマンドを与えるのでなく、expectコマンドを使って自動応答的にftpにサブコマンドを入れて、応答によって分岐しながら処理を進めるという方法もあります。 https://linuxjm.osdn.jp/html/expect/man1/expect.1.html 最初の使い始めが難しいですが。
otn

2020/02/19 13:21

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

2020/02/20 09:08

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

2020/02/21 07:09

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

0

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

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

投稿2020/02/19 09:30

t_obara

総合スコア5488

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

umino

2020/02/19 09:40

前提を詳細に書いておらずすみません。(投稿を修正しました。) batファイルを1つのみ使用できます。複数は使用できません。 もちろんscpも検討したのですが、今回、事情により使用できませんのでこの投稿をしています。(いまどきftpはあまり見ませんね...) 処理を2回に分けると以下のようですね。 1.ftp & ログ解析(ディレクトリ作成ができたか) (ここでディレクトリ作成ができなかったら終了判定できる。余計なファイル送信しなくて済む) 2.ftp & ログ解析(ファイルputができたか) ヒントをありがとうございました。
t_obara

2020/02/19 09:53

タグがLinux/Centosでbatファイル? batファイル自体は一つでもできませんか?またディレクトリが生成済みの場合送信しないで良いのですか? bashの場合、Windowsのバッチ処理よりも柔軟に処理が記載できるので、一つのスクリプトファイルで十分期待通りの動作を実現できそうですが。 (使える外部コマンドにもよりますが)
umino

2020/02/19 10:13

わたしが勝手にbatファイルモードと読んでいた(そして、<で食わせるテキストファイルにに.bat拡張子をつけた)ことから余計にわかりづらくなってしまいました。 正しくは、ftpコマンドに食わせるための、ftpコマンドを羅列したファイルのことです。(上記「ftp_cmd.bat」をご覧ください。) やりたいことは、niwatoriディレクトリが作成できてもできなくても(既にあっても)、piyo.txtをniwatoriディレクトリ内に送りたいのです。 それを、1つのスクリプト内作成した1つのbatファイルで行いたいです。 回答ありがとうございました。
t_obara

2020/02/20 01:30

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

2020/02/20 09:11

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問