2016-05-19 4 views
0

私はPerlを使用して、解釈するシステム行に文字列($ password)を渡しています。しかし、正しく解釈されていないようです。スパースバンドルを添付すると、認証に失敗したためです。注意として、パイプの後のすべてが正常に動作します。Perlシステムコールで変数が正しく解釈されない

$password = chomp($password); 

### Create the bash system call to create the sparse bundle with the password 
my $cmd = `echo $password | hdiutil create -size 200g -type SPARSEBUNDLE -encryption -stdinpass -volname \"Encrypted Storage for Matt\" -fs \"Case-sensitive Journaled HFS+\" -verbose ~/Desktop/SparseBundle`; 

いくつかのサンプル出力:

SLC1087-Matt:backups matt$ ./create_sparsebundle.pl 
DIDiskImageCreatorProbe: interface 1, score  1000, CSparseBundleDiskImage 
DIDiskImageCreatorProbe: interface 2, score -1000, CSparseDiskImage 
DIDiskImageCreatorProbe: interface 3, score -1000, CRawDiskImage 
DIDiskImageCreatorProbe: interface 7, score -1000, CWOUDIFDiskImage 
DIDiskImageCreatorProbe: interface 9, score -1000, CCFPlugInDiskImage 
DIDiskImageCreateWithCFURL: CSparseBundleDiskImage 
CBSDBackingStore::createProbe directory, not a valid image file. 
DIBackingStoreCreatorProbe: interface 0, score -1000, CBSDBackingStore 
DIBackingStoreCreatorProbe: interface 1, score  1000, CBundleBackingStore 
DIBackingStoreCreatorProbe: interface 2, score  0, CRAMBackingStore 
DIBackingStoreCreatorProbe: interface 3, score  100, CCarbonBackingStore 
DIBackingStoreCreatorProbe: interface 5, score  -100, CCURLBackingStore 
DIBackingStoreCreateWithCFURL: CBundleBackingStore 
DIFileEncodingCreatorProbe: interface 2, score  1000, CEncryptedEncoding 
DIFileEncodingCreateWithCFURL: CEncryptedEncoding 
DIFileEncodingCreatorProbe: interface 2, score -1000, CEncryptedEncoding 
DIBackingStoreCreatorProbe: interface 0, score  100, CBSDBackingStore 
DIBackingStoreCreatorProbe: interface 1, score -1000, CBundleBackingStore 
DIBackingStoreCreatorProbe: interface 2, score  0, CRAMBackingStore 
DIBackingStoreCreatorProbe: interface 3, score  100, CCarbonBackingStore 
DIBackingStoreCreatorProbe: interface 5, score  -100, CCURLBackingStore 
DIBackingStoreCreateWithCFURL: CBSDBackingStore 
DIBackingStoreCreateWithCFURL: creator returned 0 
DIFileEncodingCreateWithCFURL: creator returned 0 
DIBackingStoreCreateWithCFURL: creator returned 0 
DIDiskImageCreateWithCFURL: creator returned 0 
DI_kextWaitQuiet: about to call IOServiceWaitQuiet... 
DI_kextWaitQuiet: IOServiceWaitQuiet took 0.000003 seconds 
2016-05-18 20:59:09.627 diskimages-helper[68122:1796245] *** -[NSMachPort handlePortMessage:]: dropping incoming DO message because the connection is invalid 
hdiutil: create: returning 0 
SLC1087-Matt:backups matt$ hdiutil attach ~/Desktop/SparseBundle.sparsebundle 
Enter password to access "SparseBundle.sparsebundle": 
hdiutil: attach failed - Authentication error 

すべてが正常に動作するようですが、パスワードは明らかに間違っています。

+0

パスワードを印刷するとどうなりますか? 'system(" echo $ password ")'? – Robert

+0

これは実際にbashで動作することを確認しましたか?すなわち、perlなし。私が出会ったアプリのなかには、パスワードを使ったものがあり、その形式を使って物事を取り上げることはありません。だから、bashを開き、 'echo TheRealPassword | hdiutil create -size 200g -type SPARSEBUNDLE -encryption -stdinpass -volname \ "マット用暗号化されたストレージ\" -fs \ "大文字と小文字が区別されたHFS + \" -verbose〜/ Desktop/SparseBundle " – GregHNZ

+0

@GregHNZ、なぜですか?それは彼がPerlを使ってシェルに渡っているものではありません。 – ikegami

答えて

1

hdiutilユーティリティでは、NULLで終了するパスワードが必要です。

つまり、"mypass"は十分ではありません。パスワードには埋め込み改行のような面白い文字が含まれているため、"mypass\0"が必要です。

だから、何それは見ていますと、"mypass\n"代わりの"mypass\0"

あなたはそれがLinuxで動作するようこれを試すことができます:

echo -n -e "mypass\x00" | hdiutil ... 

しかし... AFAICT、エコーのdoesnのOSX版-eがあるので、実験する必要があります。

他のすべてが失敗した場合、echoと交換してください:

echo "mypass" | perl -e '$_ = <STDIN>; chomp ; print $_,"\x00"' 

これを表現/実行する単純な方法があるかもしれません。あなたは(passmeそれを呼び出す)は、第2のperlスクリプトを作成することができます。

#!/usr/bin/perl 
print $ARGV[0],"\x00"; 

その後passmeechoを交換してください。私は引数の前後に二重引用符を入れます。


UPDATE:

ため、私はprintfのは、コマンドにパイプする必要がありstdinpassのかなり確信しています。私はそれが正しかったかどうかわかりません。

echoおよびprintfは、コマンドにパイプされます。しかし、私はそれらをお勧めしますこれを行うにはさらに多くの方法があります。

他にも言及したように、最もきれいな方法はIPC::Run3です。それはワンストップのショッピングです。

しかし、あなたのシステム[または他のOSXシステム]にデフォルトではインストールされていない可能性があります。 Dunno - YMMV。これを調査する必要があるかもしれません。

あなたのスクリプトがの場合は、ご自身の使用のためにの場合は、上記の場合は問題ありません。しかし、他の人が使用するようにスクリプトを作成している場合、Run3を持たないシステムにスクリプトがインストールされ、sysadmはそれをインストールしません。

したがって、使いやすさと遍在性のバランスをとる必要があります。あなたのの選択肢はになります。

RUN3は、あなたがそれをパスワードを与え、その出力をキャプチャするために何が必要ですhdiutilコマンド、上両方stdinstdoutを設定します。

「パイプ」モードでperlのopen関数を使うことができます。詳細は、man perlipcを参照してください。使い方はとても簡単です。私はこれのための例を持っている - 下記を参照してください。

または、run3と同じ機能をperlの内蔵のpipeコールで実行することができます。 2本のパイプが必要です。これはちょっとした仕事なので、将来のためのものかもしれません。 [他の人が指摘したように]

echoprintf、[およびpassme]の最大の問題のアプローチがあり、彼らはパスワードを取得するためにARGVを使用しているため、彼らは他のプロセス[簡潔]にそれを「ブリード」ということです。

だから、私たちは安全な方法を望んでいます。 Run3は]。そのため、hdiutilはコマンドライン引数の代わりにstdinにパスワードを取得します。


(1)実際には、最も簡単な方法は、一時ファイルにパスワードをダンプすることがあります

use Fcntl; 

my $fd; 
my $tmp = "/tmp/pwfile"; 

my $password = "whatever"; 

# NOTE: by using sysopen and setting the 600 permission atomically, we avoid a 
# race condition that may allow another user to open this file 
unlink($tmp); 
sysopen($fd,$tmp,O_WRONLY | O_CREAT | O_EXCL,0600) or 
    die("unable to open '$tmp' -- $!\n"); 
syswrite($fd,$password . "\x00"); 
close($fd) 

my $cmd = `hdiutil ... < $tmp`; 
unlink($tmp); 

(2)パスワードを書き込むしたくない場合一時ファイルは、たとえ短くてもそれが残っていても、別の方法があります。上記のpassmeスクリプトアプローチに似ていますが、を除いて、を除いて、パスワードを環境変数として渡します。これにより、コマンドライン引数によるパスワードの公開が回避されます。ここで

passme変種です:

#!/usr/bin/perl 
print($ENV{"PASSME"},"\x00"); 

これは、インラインでもを行うことができます。

perl -e 'print($ENV{"PASSME"},"\x00")' 

その後、スクリプトは次のようになります。

my $password = "whatever"; 

$ENV{"PASSME"} = $password; 
my $cmd = `passme | hdiutil ...`; 
delete($ENV{"PASSME"}); 

(3 )さらに別の方法pipeモードのperlのopenの[上記の]使用を使用しています。 hdiutilへの入力パイプとして設定し、コマンド実行後に読み取った一時ファイルに出力を振り分けてください。

my $fdout; 
my $fdin; 
my $tmp = "/tmp/results"; 
my $buf; 

my $password = "whatever"; 

open($fdout,"| hdiutil ... > $tmp") || 
    die("unable to open hdiutil pope -- $!\n"); 
print($fdout $password,"\x00"); 
close($fdout); 

open($fdin,"<$tmp") || 
    die("unable to open '$tmp' -- $!\n"); 
while ($buf = <$fdin>) { 
    chomp($buf); 
    # do whatever ... 
} 
close($fdin); 
+0

3つの無関係なプロセスなしで、 'use IPC :: Run3 qw(run3);を使用してマシン上の全員にパスワードを表示せずに行うこともできます。 – ikegami

+0

いいえ、「$ password」を割り当てられているので、表示されているのは '1 \ n" 'です(これは' '$ password \ ''、' '$ password \ 'chomp'の戻り値 –

+0

移植性のために: 'echo -e'の代わりに' printf'を使用してください。 – oals

6

返品についてはchompをご覧ください。あなたのコードは少なくとも変数を整数0または1と書き換えます。それは私の目を引いた。


chompは、すべての引数から削除された文字の合計数を返します。

+0

'chomp'を削除しましたが、まだ問題があります。私はアップアップを見せてくれるものを更新します。 –

関連する問題