Programing

Rakefile에서 bash 명령 실행

lottogame 2020. 11. 13. 07:45
반응형

Rakefile에서 bash 명령 실행


.NET Framework에서 여러 bash명령 을 실행하고 싶습니다 Rakefile.

나는 내에서 다음을 시도했다. Rakefile

task :hello do
  %{echo "World!"}
end

그러나 실행시 rake hello출력이 없습니까? Rakefile에서 bash 명령을 어떻게 실행합니까?

참고 : 이것은 Rakefile 에서 bash 명령을 실행하는 방법을 구체적으로 묻는 것이므로 중복이 아닙니다 .


rake가 이것을 원하는 방식은 http://rubydoc.info/gems/rake/FileUtils#sh-instance_method 예 :

task :test do
  sh "ls"
end

내장 rake 함수 sh는 명령의 반환 값을 처리하고 (명령에 0이 아닌 반환 값이있는 경우 작업이 실패 함) 추가로 명령 출력도 출력합니다.


Ruby에서 쉘 명령을 실행하는 방법에는 여러 가지가 있습니다. 간단한 방법 (가장 일반적인 방법)은 백틱을 사용하는 것입니다.

task :hello do
  `echo "World!"`
end

백틱은 셸 명령의 표준 출력이 반환 값이되는 좋은 효과가 있습니다. 예를 들어 다음 ls을 수행 하여 출력을 얻을 수 있습니다.

shell_dir_listing = `ls`

그러나 쉘 명령을 호출하는 다른 많은 방법이 있으며 모두 장점 / 단점을 가지며 다르게 작동합니다. 이 문서 에서는 선택 사항에 대해 자세히 설명하지만 다음은 간단한 요약 가능성입니다.


합의가 rake의 #sh방법 을 선호하는 것처럼 보이지만 OP는 명시 적으로 bash를 요청하므로이 답변은 약간의 사용이있을 수 있습니다.

이것은 쉘 명령을 실행하기 Rake#sh위해 Kernel#system호출을 사용하기 때문에 관련이 있습니다. Ruby /bin/sh는 사용자가 구성한 셸 또는 $SHELL환경을 무시하고이를에 하드 코딩 합니다.

다음은에서 bash를 호출 /bin/sh하여 sh메서드 를 계속 사용할 수 있도록 하는 해결 방법입니다.

task :hello_world do
  sh <<-EOS.strip_heredoc, {verbose: false}
    /bin/bash -xeuo pipefail <<'BASH'
    echo "Hello, world!"
    BASH
  EOS
end

class String
  def strip_heredoc
    gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, ''.freeze)
  end
end

#strip_heredoc 레일에서 차용 :

https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/string/strip.rb

아마도 active_support를 요구하여 얻을 수 있거나 레일 프로젝트에있을 때 자동으로로드 될 수 있습니다. 그러나 저는이 외부 레일을 사용하고 있었기 때문에 직접 정의해야했습니다.

여기에는 마커가있는 외부 문서와 마커 EOS가있는 내부 문서가 있습니다 BASH.

이것이 작동하는 방식은 BASH 마커 사이의 내부 heredoc을 bash의 stdin에 공급하는 것입니다. 의 컨텍스트 내에서 실행 /bin/sh되므로 루비가 아닌 posix heredoc입니다. 일반적으로 끝 표식이 열 1에 있어야하지만 들여 쓰기 때문에 여기에서는 그렇지 않습니다.

However, because it's wrapped within a ruby heredoc, the strip_heredoc method applied there deindents it, placing the entirety of the left side of the inner heredoc in column 1 prior to /bin/sh seeing it.

/bin/sh also would normally expand variables within the heredoc, which could interfere with the script. The single quotes around the start marker, 'BASH', tell /bin/sh not to expand anything inside the heredoc before it is passed to bash.

However /bin/sh does still apply escapes to the string before passing it to bash. That means backslash escapes have to be doubled to make it through /bin/sh to bash, i.e. \ becomes \\.

The bash options -xeuo pipefail are optional.

The -euo pipefail arguments tell bash to run in strict mode, which stops execution upon any failure or reference to an undefined variable, even a command in a pipeline. This will return an error to rake, which will stop the rake task. Usually this is what you want. The arguments can be dropped if you want normal bash behavior.

The -x option to bash and {verbose: false} argument to #sh work in concert so that rake only prints the bash commands which are actually executed. This is useful if your bash script isn't meant to run in its entirety, for example if it has a test which allows it to exit gracefully early in the script.

Be careful to not set an exit code other than 0 if you don't want the rake task to fail. Usually that means you don't want to use any || exit constructs without setting the exit code explicitly, i.e. || exit 0.

If you run into any bash weirdness along the way, turn off the -o pipefail. I've seen a bit of bugginess related to it specifically when pipelining to grep.


%{echo "World!"} defines a String. I expect you wanted %x{echo "World!"}.

%x{echo "World!"} executes the command and returns the output (stdout). You will not see the result. But you may do:

puts %x{echo "World!"}

There are more ways to call a system command:

  • Backticks: `
  • system( cmd )
  • popen
  • Open3#popen3

There are two ways:

sh " expr "

or

%x( expr )

Mind that ( expr ) can be { expr } , | expr | or ` expr `

The difference is, sh "expr" is a ruby method to execute something, and %x( expr ) is the ruby built-in method. The result and action are different. Here is an example

task :default do
value = sh "echo hello"
puts value
value = %x(echo world)
puts value
end

get:

hello  # from sh "echo hello"
true   # from puts value
world  # from puts value

You can see that %x( expr ) will only do the shell expr but the stdout will not show in the screen. So, you'd better use%x( expr ) when you need the command result.

But if you just want to do a shell command, I recommend you use sh "expr". Because sh "irb" will make you go into the irb shell, while %x(irb) will dead.

참고URL : https://stackoverflow.com/questions/9796028/execute-bash-commands-from-a-rakefile

반응형