如何使特定的命令行程序可供在Automator中运行的Ruby代码使用

huangapple go评论75阅读模式
英文:

How to make specific command line programs usable by Ruby code running in Automator

问题

以下是您要翻译的内容:

在Ruby中,有许多方法可以进行系统调用。

我目前在一个方法中使用open3,就像这样:

def run_system_command { |system_command|
   
  stdout_str = ""
  stderr_str = ""
  status = ""
 
  Open3.popen3(system_command) do |stdin, stdout, stderr, wait_thr|
     stdin.close                
     stdout_str = stdout.read   # 将stdout读取为字符串。注意这会阻塞,直到命令执行完成!
     stderr_str = stderr.read   # 将stderr读取为字符串
     status = wait_thr.value    # 将阻塞,直到命令完成;返回响应`.success?`等的状态
  end
 
  return stdout_str, stderr_str, status
}

当运行基本的系统命令如 tarlscd 时,它运行正常...

但是,当我尝试从Automator的“Run Shell Script”中运行 ios-deploy 这样的程序时,我没有得到任何结果:

如何使特定的命令行程序可供在Automator中运行的Ruby代码使用

(假设run_system_command方法在代码块中定义。Automator文本字段不会扩展,所以我无法向您展示整个内容)

在这种调用中,我没有任何输出,这让我认为在Ruby中进行系统调用时无法找到 ios-deploy 程序。

请注意,我确保我可以通过在简单的“Hello World”“Run Shell Script”操作中使用“Set Value of Variable”和“Display Notification”操作来从Ruby中获取输出。

我应该如何告诉Ruby如何使用/在哪里找到该程序?

是否有某种路径调整的方法?我不确定在调用Ruby时在哪里进行这样的更改。

更新:通过使用程序的完整路径,我能够使命令正常工作:

/usr/local/bin/ios-deploy

是否有一种方法可以告诉Ruby/Automator在不必每次都显式使用路径前缀的情况下找到该程序?

英文:

There are many ways in ruby to make a system call.

I'm currently using open3 in a method like this:

def run_system_command { |system_command|
   
  stdout_str = ""
  stderr_str = ""
  status = ""
 
  Open3.popen3(system_command) do |stdin, stdout, stderr, wait_thr|
     stdin.close                
     stdout_str = stdout.read   # read stdout to string. note that this will block until the command is done!
     stderr_str = stderr.read   # read stderr to string
     status = wait_thr.value    # will block until the command finishes; returns status that responds to .success? etc
  end
 
  return stdout_str, stderr_str, status
}

It works fine when running basic system commands like tar or ls or cd etc...

But when I try to run a program like ios-deploy from an Automator 'Run Shell Script', I don't get any results:

如何使特定的命令行程序可供在Automator中运行的Ruby代码使用

(Assume the run_system_command method is defined in the block. Automator text fields don't expand so I couldn't show you the whole thing)

I get no output from such a call, which makes me think that making a system call in Ruby doesn't see the ios-deploy program.

Note that I've made sure that I can get output from Ruby in general by using 'Set Value of Variable' and 'Display Notification' actions in a simple "Hello World" 'Run Shell Script' action.

How can I tell ruby how to use / where to find the program?

Some kind of path adjustment? I'm not sure where to make such a change when calling Ruby in this way.

Update: I'm able to get the command to work by using the full path to the program:

/usr/local/bin/ios-deploy

Is there a way to tell Ruby/Automator where to find that program without having to explicitly use the path prefix every time?

答案1

得分: 1

Automator 运行 Ruby(以及其他 shell 脚本)时使用的环境中,PATH 设置为 /usr/bin:/bin:/usr/sbin:/sbin,也就是它只会在 /usr/bin/bin/usr/sbin/sbin 中搜索可执行文件。

我没有看到在 Automator 中配置环境的方法,但至少你可以通过 ENV#[]= 在 Ruby 中修改环境,例如:

ENV['PATH'] = "/usr/local/bin:#{ENV['PATH']}"

这样,在运行 shell 命令时,/usr/local/bin 中的可执行文件将变得可用:

Open3.popen3 也接受环境变量作为参数:(查看 Process.spawn 的文档)

require 'open3'

env = { 'PATH' => "/usr/local/bin:#{ENV['PATH']}" }
command = 'brew --version'

Open3.popen3(env, command) do |stdin, stdout, stderr, wait_thr|
  # ...
end
英文:

> Is there a way to tell Ruby/Automator where to find that program without having to explicitly use the path prefix every time?

Kind of. Automator runs Ruby (as well as the other shell scripts) using an environment with PATH set to /usr/bin:/bin:/usr/sbin:/sbin, i.e. it will only search for executables in /usr/bin, /bin, /usr/sbin and /sbin.

I don't see any way to configure the environment in Automator, but at least you can modify the environment in Ruby via ENV#[]=, e.g.:

ENV['PATH'] = "/usr/local/bin:#{ENV['PATH']}"

This way, executables in /usr/local/bin will become available when running a shell command:

如何使特定的命令行程序可供在Automator中运行的Ruby代码使用

Open3.popen3 also accepts environment variables as an argument: (see the docs for Process.spawn)

require 'open3'

env = { 'PATH' => "/usr/local/bin:#{ENV['PATH']}" }
command = 'brew --version'

Open3.popen3(env, command) do |stdin, stdout, stderr, wait_thr|
  # ...
end

huangapple
  • 本文由 发表于 2023年7月13日 13:29:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76676189.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定