🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
bash

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

Q&A

解決済

3回答

11497閲覧

シェルスクリプトでsftp接続し、ファイル転送を行いたい。

退会済みユーザー

退会済みユーザー

総合スコア0

bash

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

1グッド

0クリップ

投稿2022/01/20 02:18

編集2022/01/20 09:13

現在ローカルサーバのログファイルをsftp接続し、リモートサーバへ転送するシェルスクリプトを作成しております。
その際に、ローカルサーバによってディレクトリが存在するものと存在しないサーバがあります。
そこで、シェルスクリプトでディレクトリの存在チェックを行い、存在しないものはmputコマンドを実行しないようにしたいです。(サーバ毎に中身を変えることはしたくはないです。)
■仕様
・ログファイル転送元のサーバは複数存在します。
・ログは3日分のログを転送します。

現在のプログラム

#!/bin/bash # ローカルの3日分のファイルを変数に格納 LOG1=(`find /var/log/sample*.gz -mtime +0 -and -mtime -4`) LOG2=(`find /var/log/test/sample*.lgz -mtime +0 -and -mtime -4`) # SFTP接続 sftp -i /home/user/.ssh/id_rsa username@aa.bb.cc.dd << END cd /log/$1/ # LOG1の3日分のログを送信 mput ${LOG1[0]} mput ${LOG1[1]} mput ${LOG1[2]} # LOG2の3日分のログを送信 mput ${LOG2[0]} mput ${LOG2[1]} mput ${LOG2[2]} # SFTP切断 quit END

上記を実行したところ下記のようになります。

find: '/var/log/test/sample*.gz': No such file or directory Connected to aa.bb.cc.dd sftp> cd /var/server01/ sftp> # ↓LOG1に該当ファイルが格納されたため、実行できている。 sftp> mput /var/log/sample-20220119.gz Uploading /var/log/sample-20220119.gz to /log/server01/sample-20220119.gz /var/log/sample-20220119.gz 100% 1000 10.0MB/s 00:00 省略 # ↓LOG2に該当ファイルが格納されなかったため、叩く変数が存在しない。 sftp> mput You must specify at last one path after a mput command. 省略 sftp> sftp> quit

懸念点・自分で試したこと

現状困っている点は、3点です。
▼1点目
「find: '/var/log/test/sample*.gz': No such file or directory」のようにtestディレクトリが存在しない場合に変数に格納はされないが、エラーが出てしまう。
こちらをif文を使用し、回避しようと下記のように実装しました。

if [ LOG1=(`find /var/log/sample*.gz -mtime +0 -and -mtime -4`) ]; then echo "存在する" fi

そうすると、test文の中で()は使えないとのこと。

▼2点目
上記の問題が解決できた際に、sftp接続し、mputコマンドによってファイルを転送するのですが、

sftp> mput You must specify at last one path after a mput command.

のように転送はされないようになっているが、mputコマンド自体は叩いてしまっているので、1点目の存在チェックで存在しないと判定された場合、mputコマンドを実行しないようにしたい。
こちらもif文等で試してみましたが、そもそもsftpでif文は使えないのでは?と思い、詰まっている状況です。

▼3点目
現状3日分のファイルを転送するために、mputコマンドを3回ずつ叩くようにしているが、1回のmputコマンドで
3日分のログファイルを転送することが出来るか。
こちらは、mput ${LOG1[@]}など、忘れてしまいましたがその他にも試行錯誤は行いました。
上記の結果だと、下記のように認識されてしまいました。

mput /var/log/sample-20220119.gz , /var/log/sample-20220118.gz, /var/log/sample-20220117.gz

上記の問題について解決方法がお分かりの方がいらっしゃいましたらご教授頂けますと幸いです。
1点目、2点目、3点目全てご回答頂かなくても1つのご回答でも大変助かります。
よろしくお願いいたします。

melian👍を押しています

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

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

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

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

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

guest

回答3

0

ベストアンサー

一点目:
一般には、配列の要素数を調べます。

Bash

1LOG1=(`find ~~~`) 2if [ ${#LOG1[@]} -gt 0 ]; then 3 echo "存在する" 4fi

findはエラーが無ければ結果が0件でも正常終了なので、一般には$?での判断は出来ません。
ただし、今回のfindだと「No such file or directory」というエラーになるので$?でも判断できますが。

Bash

1if LOG1=(`find ~~~`) ; then 2 echo "存在する" 3fi

二点目:
sftpの中で条件判断など出来ないので、外側で考えます。上記を使うと、

Bash

1LOG1=(`find /var/log/sample*.gz -mtime +0 -and -mtime -4`) 2LOG2=(`find /var/log/test/sample*.lgz -mtime +0 -and -mtime -4`) 3 4CMD1= 5for a in "${LOG1[@]}" 6do CMD1+="put $a"$'\n' 7done 8CMD2= 9for a in "${LOG2[@]}" 10do CMD2+="put $a"$'\n' 11done 12 13# SFTP接続 14sftp -i /home/user/.ssh/id_rsa username@aa.bb.cc.dd << END 15cd /log/$1/ 16 17# LOG1の3日分のログを送信 18$CMD1 19# LOG2の3日分のログを送信 20$CMD2 21 22# SFTP切断 23quit

三点目:
mputできるはずですが、
⇒ sftpのmputでは出来ないようです。

上記の結果だと、下記のように認識されてしまいました。

そのカンマは何ですかね?

全般:
findは改善の余地がありますが、とりあえずそのままにしてあります。
最初からif [ -d /var/log/test ]で分岐する案もあるでしょう。

##訂正
mputに複数ファイルを指定出来ないので、訂正。

投稿2022/01/20 04:26

編集2022/01/20 07:26
otn

総合スコア85862

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

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

退会済みユーザー

退会済みユーザー

2022/01/20 05:15

ご回答頂きありがとうございます。 また、丁寧に分かりやすくご説明頂きありがとうございます。 > そのカンマは何ですかね? すみません。こちらカンマではなく、送信先として認識されるようです。 ``` sftp> mput /var/log/sample-20220117.gz /var/log/sample-2022018.gz /var/log/sample-20220119.gz Uploading /var/log/sample-20220117.gz to /var/log/sample-20220118.gz remote open("/var/log/sample-20220118.gz"):No such file or directory sftp> ``` また、otn様から頂いた2つ目のコードにて実装してみました。 実行結果も上記と同じ結果となりました。。
退会済みユーザー

退会済みユーザー

2022/01/20 06:30

度々すみません。 一点目の懸念点ですが、otn様から頂いた「最初からif [ -d /var/log/test ]で分岐する案もあるでしょう。」を 参考にさせていただき下記のように実装することで、「No such file or directory」エラーが出ないようにすることが出来ました。ありがとうございます。 ``` LOG1_PATH="/var/log" LOG2_PATH="/var/log/test" if [ -d $LOG1_PATH ]; then LOG1=(`find $LOG1_PATH/sample*.gz -mtime +0 -and -mtime -4`) fi if [ -d $LOG2_PATH ]; then LOG2=(`find $LOG2_PATH/sample*.gz -mtime +0 -and -mtime -4`) fi ```
otn

2022/01/20 06:59

エラーを出さない普通のfindの使い方は、 find $LOG1_PATH -name "sample*.gz" -mtime +0 -and -mtime -4 です。
otn

2022/01/20 07:08

すいません。ftpのmputと同じだと思っていましたが、sftpのmputは仕様が違うようで、複数の記述は出来ないですね。 修正しておきます。
退会済みユーザー

退会済みユーザー

2022/01/20 09:19 編集

> エラーを出さない普通のfindの使い方は、 すみません。ありがとうございます。 無事、ディレクトリやファイルの存在チェックしてエラー文を回避できる実装が出来ました! > ftpのmputと同じだと思っていましたが、sftpのmputは仕様が違うようで、複数の記述は出来ないですね。 sftpでは出来ないのですね。ご共有頂きありがとうございます。 また、修正頂きありがとうございます。 大変助かりました。。本当にありがとうございます!
guest

0

exit status と条件に適合するログファイルの個数を調べてみてはどうでしょうか。

bash

1LOG2=(`find /var/log/test/sample*.lgz -mtime +0 -and -mtime -4 2>/dev/null`) 2if [ $? -ne 0 ] || [ ${#LOG2[@]} -eq 0 ]; then 3 echo 'Warning: None log file in LOG2' >&2 4fi

また、ログファイルがある場合にのみ転送を行う様にします。

bash

1function mput_log2() { 2 if [ ${#LOG2[@]} -gt 0 ];then 3 [ ${#LOG2[@]} -gt 3 ] && LOG2=(${LOG2[@]:0:3}) 4 for l in ${LOG2[@]}; 5 do 6 echo "put $l" 7 done 8 fi 9} 10 11# SFTP接続 12sftp -i /home/user/.ssh/id_rsa username@aa.bb.cc.dd << END 13cd /log/$1/ 14 15# LOG1の3日分のログを送信 16mput ${LOG1[0]} 17mput ${LOG1[1]} 18mput ${LOG1[2]} 19# LOG2の3日分のログを送信 20$(mput_log2) 21 22# SFTP切断 23quit 24END

投稿2022/01/20 03:09

編集2022/01/20 04:52
melian

総合スコア20592

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

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

退会済みユーザー

退会済みユーザー

2022/01/20 05:17

ご回答頂きありがとうございます。 このように実装する方法があるのですね! ありがとうございます。参考にさせて頂きます! ただ、シェルスクリプトにはあまり慣れていなく、少し私には難しく感じました。私の力不足です。
guest

0

find /var/log/sample*.gz -mtime +0 -and -mtime -4

findコマンドの起点は、ディレクトリでしょう。 https://linuxjm.osdn.jp/html/GNU_findutils/man1/find.1.html
こうすればいいのでは?

find /var/log -name 'sample*.gz' -and -mtime +0 -and -mtime -4

mputコマンドを実行しないようにしたい。

mputコマンドを実行してエラーになっても、無視すればいいだけでは? 実行結果をチェックしている風はないので。

sftp -i /home/user/.ssh/id_rsa username@aa.bb.cc.dd 2>/dev/null << END

投稿2022/01/20 02:30

shiketa

総合スコア4052

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

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

退会済みユーザー

退会済みユーザー

2022/01/20 06:22

ご回答頂きありがとうございます。 > こうすればいいのでは? こちらについては無事解決しました。ありがとうございます。 > mputコマンドを実行してエラーになっても、無視すればいいだけでは? 実行結果をチェックしている風はないので。 こちらはshiketa様の仰る通りです。 ただ一番はやはり実行しないことかと思いますので、実装が難しければshiketa様から頂いた「/dev/null」として出力結果を捨てる形で対応したいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問