メインコンテンツへスキップ
前回のブログではFTPを用いたファイル転送の自動化について述べました。FTP利用には三つの問題があります。第一に、パスワードが平文でネットワーク上を送信されるため、プロトコルアナライザを持つ者なら誰でも入手可能です。第二に、データも平文で送信されます。 第三に、パスワードをマクロ内か.netrcファイルのいずれかに記録する必要があります。これらの問題から、多くのサイトではFTPの代わりにSSHのセキュアFTPサブシステムであるSFTPの使用を義務付けたり、義務化を検討したりしています。しかし、コマンドマクロ内で単純にftpをsftpに置き換えただけでは(図1)、正常に動作するとは限りません(図2)。

 

&attach_input
sftp 172.16.1.116
nd
MYPASSWORD
put foo
&if (command_status) ^= 226 &then &goto ERROR1
get bar
&if (command_status) ^= 226 &then &goto ERROR2
quit
&
&label ERROR1
..display_line Could not put file
quit
&return
&
&label ERROR2
..display_line Could not get file
quit
&return

図1 – sftp1.cm – コマンドマクロ内でftpコマンドをsftpに置き換える

 

sftp1
Connecting to 172.16.1.116...
dup2: Bad file number.
Error on line 3 of sftp1.
command_processor: Object not found. nd. In command macro
%phx_vos#m15_mas>SysAdmin>Noah_Davids>sftp1.cm
ready  12:39:59

 

図2 – sftp1.cmの実行
問題は、ネイティブVOSコマンドとPOSIXオープンソースが入力を扱う方法の非互換性です。しかし、SFTPはFTPと同様に、要求のリストを含むファイルを作成でき(図3)、それを自動的に実行します(図4)。

 


put foo
get bar

 

図3 – sftp2.input – sftpが実行するリクエストを含むファイル

 


sftp -b sftp2_input [email protected]
[email protected]'s password:
sftp> put foo
Uploading foo to /SysAdmin/Noah_Davids/foo
sftp> get bar
Couldn't stat remote file: No such file or directory
File "/SysAdmin/Noah_Davids/bar" not found.
Ready  13:06:45

 

図4 – リクエストの入力ファイルとパスワードプロンプトを用いた実行
図4でsftpがパスワード入力を要求していることに気づくでしょう。入力ファイルにパスワードを記述する方法はありません。パスワードプロンプトを回避する唯一の方法は、公開鍵認証を使用することです(図5)。

 

sftp -b sftp2_input [email protected]
sftp> put foo
Uploading foo to /SysAdmin/Noah_Davids/foo
sftp> get bar
Couldn't stat remote file: No such file or directory
File "/SysAdmin/Noah_Davids/bar" not found.
Ready  13:12:28

 

図5 – 要求の入力ファイルを用いた実行。パスワードプロンプトを排除するため公開鍵認証を使用

 

公開鍵認証の設定方法に関する記事はこちらでご覧いただけます – http://members.cox.net/ndav1/self_published/publickey_authentication_setup.html

残念ながら、sftpは入力ファイル内のすべての要求を順番に実行するだけで、転送が成功したかどうかをテストする仕組みはありません。

コマンドマクロが使用できない場合、代替手段はありますか?gnu_tools製品にはexpectというプログラムが同梱されています。これはコマンド送信、任意の数の異なる応答待ち、出力ストリームの内容に基づく処理実行に使用できます。私はexpectの専門家ではありませんが、図6のスクリプトが導入の助けとなるでしょう。「expectスクリプト」でウェブ検索すれば、私の簡易例をカスタマイズするのに役立つ多くの参考資料が見つかります。

 

# If we get an end-of-file (eof) it means that the sftp process
# terminated. Report the last command that was sent.
#
proc goteof {cmd} {
puts "sftp connection unexpectedly closed n"
puts "last text received wasn"
puts "<<"
puts $cmd
puts ">>nnn"
exit
}
# この手順は、キー文字列を検索する正規表現の一致処理を行います
# 実行されたコマンドから収集された出力において。この場合
# 私は単にエラーの種類を報告しているだけで、他の対応も可能です
# 同様に。私も2つのエラーしか確認していません。他にもあります。あなたは
# 見つけたものから追加していく。
#
proc checkforerrors {buf cmd} {
if [正規表現 {.*not found} $buf] {
「$cmd FAILED : not found」と出力する
1を返す
}
if [regexp {.*Permission denied} $buf] {
「$cmd FAILED : アクセス問題が発生しました」と出力します
1を返す
}
return 0
タイムアウトを-1に設定し、タイムアウトを無効化します。デフォルトは10秒です。
# そしてほとんどのファイル転送はそれよりも時間がかかる。私は設定しないことに決めた
# タイムアウト、変更可能です。
タイムアウトを設定 -1

# start sftp
spawn sftp[email protected]

# sftpプロンプトを待機するが、認証プロンプト(
で終わる)が表示された場合 # yes/no セキュリティ問題を報告して終了する。
expect {
“yes/no?” { puts
“nnn間違ったサーバーに接続したか、サーバーが再読み込みされました。”
puts
“このスクリプトを再度実行するには、サーバーキーの検証が必要です。nnn”
exit }
sftp>
}

# テスト用の便利なディレクトリに変更
send "cd sftp_testr"
expect {
eof { goteof "cd sftp_test" }
sftp>
}

#
プロンプトで収集した全文字列を引数にエラーチェックを実行 # sftp>プロンプトも対象。sftpに送信したコマンドも同様。
# checkforerrorsプロシージャが1を返した場合、スクリプトを終了。他の処理も実行可能

if {[checkforerrors $expect_out(buffer) “cd sftp_test”] == 1} { exit }

send "put foor"
expect {
eof { goteof "put foo" }
sftp>
}
if {[checkforerrors $expect_out(buffer) "put foo"] == 1} { exit }

send "get barr"
expect {
eof { goteof "get bar" }
sftp>
}
if {[checkforerrors $expect_out(buffer) "get bar"] == 1} { exit }

send "quitr"
expect eof
puts "script donenn"

 

図6 – sftp3.exp – SFTPを自動化するexpectスクリプト

 

expect sftp3.exp
spawn sftp [email protected]
Connecting to 172.16.1.116...
The authenticity of host 172.16.1.116(172.16.1.116)' can't be established
+.
RSA key fingerprint is 37:f4:1a:56:64:af:ab:8a:7c:0b:36:47:c5:6c:1d:1a.
Are you sure you want to continue connecting (yes/no)?
間違ったサーバーに接続したか、サーバーが再読み込みされました。
このスクリプトを再度実行するには、サーバーキーの検証が必要です。ready 10:41:10

 

図7 – セキュリティ警告を伴うsftp3.exp expectスクリプトの実行

 

expect sftp3.exp
spawn sftp [email protected]
Connecting to 172.16.1.116...
sftp> cd sftp_test
sftp> put foo
Uploading foo to /SysAdmin/Noah_Davids/sftp_test/foo
sftp> get bar
リモートファイルを統計処理できませんでした: ファイルまたはディレクトリが見つかりません
ファイル "/SysAdmin/Noah_Davids/sftp_test/bar" が見つかりません。
sftp> get bar FAILED : not foundready 10:42:11

 

図8 – 警告は出ないが転送に失敗したsftp3.exp expectスクリプトの実行

最後に、私のFTPブログで述べたように、FTPは開かれたままのファイルを読み取ることが可能であり、これが原因で不完全なファイルが転送されることがありました。そこで提案したのは、FTPマクロが特定の場所にファイルが出現するのを待機し、その後転送する場合、そのファイルがロック解除されていることを確認すべきだということです。同じ問題はSFTPでも発生し得ますが、解決策は同様です。 ファイルロックチェックをコマンドマクロ(図9)に配置し、ファイルのロックが解除された時点で適切なスクリプトを実行するexpectを呼び出せます。

&label AGAIN
&if (exists new_file) = 1 & (locked new_file) = 0 &then &goto EXPECT
display_line new_file not ready for transfer as of (time)
sleep -seconds 15
&goto AGAIN
&
&
&label EXPECT
expect sftp3.exp

 

図9 – expect呼び出し前のファイルロック確認のためのコマンドマクロテスト

© 2024 ストラタス・テクノロジーズ