我正在尝试编写一个与Android ADB命令交互的gem。我无法理解如何将参数传递给子流程。
我正在使用POpen4 gem,它只是特定于open3 / open4模块的平台的包装器。在OSX上,我运行以下命令,然后返回所需的输出:
>> require 'POpen4'
=> true
>> POpen4::popen4("/Library/android-sdk-mac_x86/platform-tools/adb shell pm list packages -f") do |pout, perr, pin|
?> pout.each { |line| puts line.to_s.strip }
>> end
package:/system/app/Fallback.apk=com.android.fallback
package:/system/app/SoundRecorder.apk=com.android.soundrecorder
..<snip>..
package:/system/app/VpnServices.apk=com.android.server.vpn
=> #<Process::Status: pid=13833,exited(0)>
当我在Win32上运行时,我得到:
irb(main):001:0> require 'POpen4'
=> true
irb(main):002:0> POpen4::popen4("C:\\Android\\android-sdk-windows\\platform-tools\\adb.exe shell pm list packages -f")
Errno::ENOENT: No such file or directory - C:\Android\android-sdk-windows\platform-tools\adb.exe shell pm list packages -f
from C:/Ruby192/lib/ruby/1.9.1/open3.rb:202:in `spawn'
from C:/Ruby192/lib/ruby/1.9.1/open3.rb:202:in `popen_run'
from C:/Ruby192/lib/ruby/1.9.1/open3.rb:90:in `popen3'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/win32-open3-19-0.0.1/lib/win32/open3.rb:5:in `popen4'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/POpen4-0.1.4/lib/popen4.rb:48:in `popen4'
from (irb):2
from C:/Ruby192/bin/irb:12:in `<main>'
如果我使用procexp监视Ruby正在做什么,我可以看到它将popen4
的整个参数视为要运行的命令:
ruby.exe 5800 QueryDirectory C:\Android\android-sdk-windows\platform-tools\adb.exe shell pm list packages -f.exe NO SUCH FILE
ruby.exe 5800 QueryOpen C:\Android\android-sdk-windows\platform-tools\adb.exe shell pm list packages -f.exe FAST IO DISALLOWED
ruby.exe 5800 CreateFile C:\Android\android-sdk-windows\platform-tools\adb.exe shell pm list packages -f.exe NAME NOT FOUND
ruby.exe 5800 QueryDirectory C:\Android\android-sdk-windows\platform-tools\adb.exe shell pm list packages -f.com NO SUCH FILE
ruby.exe 5800 QueryOpen C:\Android\android-sdk-windows\platform-tools\adb.exe shell pm list packages -f.com FAST IO DISALLOWED
ruby.exe 5800 CreateFile C:\Android\android-sdk-windows\platform-tools\adb.exe shell pm list packages -f.com NAME NOT FOUND
ruby.exe 5800 QueryDirectory C:\Android\android-sdk-windows\platform-tools\adb.exe shell pm list packages -f.cmd NO SUCH FILE
ruby.exe 5800 QueryOpen C:\Android\android-sdk-windows\platform-tools\adb.exe shell pm list packages -f.cmd FAST IO DISALLOWED
ruby.exe 5800 CreateFile C:\Android\android-sdk-windows\platform-tools\adb.exe shell pm list packages -f.cmd NAME NOT FOUND
ruby.exe 5800 QueryDirectory C:\Android\android-sdk-windows\platform-tools\adb.exe shell pm list packages -f.bat NO SUCH FILE
ruby.exe 5800 QueryOpen C:\Android\android-sdk-windows\platform-tools\adb.exe shell pm list packages -f.bat FAST IO DISALLOWED
ruby.exe 5800 CreateFile C:\Android\android-sdk-windows\platform-tools\adb.exe shell pm list packages -f.bat NAME NOT FOUND
ruby.exe 5800 CreateFile C:\Android\android-sdk-windows\platform-tools\adb.exe shell pm list packages -f NAME NOT FOUND
ruby.exe 5800 CreateFile C:\Android\android-sdk-windows\platform-tools\adb.exe shell pm list packages -f NAME NOT FOUND
虽然popen3
文档说这应该被视为命令行和参数:
The parameters +cmd…+ is passed to Process.spawn. So a commandline string and list of argument strings can be accepted as follows.
Open3.popen3("echo a") {|i, o, e, t| ... }
Open3.popen3("echo", "a") {|i, o, e, t| ... }
Open3.popen3(["echo", "argv0"], "a") {|i, o, e, t| ... }
我在这里缺少什么?