質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails 3

Ruby on Rails3はRubyによって書かれたオープンソースのウェブフレームワークです。Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

sh

shは、UNIX系OSのシェル操作の1つであり、最も基本的なシェルのことです。

Q&A

解決済

1回答

2209閲覧

Railsで別サーバのシェルスクリプトを非同期で実行したい

nonsuke0113

総合スコア1

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails 3

Ruby on Rails3はRubyによって書かれたオープンソースのウェブフレームワークです。Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

sh

shは、UNIX系OSのシェル操作の1つであり、最も基本的なシェルのことです。

0グッド

0クリップ

投稿2020/07/31 10:01

編集2020/08/01 05:50

実現したいこと

Ruby on Rails(3.0.5)で出来たページにて、ボタン押下時に、別サーバにあるシェルスクリプトを非同期で実行したい(すぐ同じページにリダイレクトして操作できるようにしたい)です。

上記スクリプトは、cronで定時実行されているため、ボタン押下後、多重起動でスクリプトが実行できなかった時と、実行できた時に、それぞれ別のフラッシュメッセージを表示したいです。

ただし、そのスクリプトの処理は、別サーバとやりとりして、画像を加工するなど、かなり時間がかかる為、シェルスクリプトが起動できたかどうか判別できた後は、シェルスクリプトの完了を待たず、フラッシュメッセージを表示したいです。
→シェルスクリプトの起動ができたかどうかはRubyのcontroller側で受け取りたいが、その後は別サーバで勝手に処理を実行していて欲しいです。

試したこと

  • スクリプト側で多重起動チェックを行うようにしました。
  • 多重起動時は、標準出力に"already"という文字列を出力し、多重起動していなければ、本来スクリプトで実行される処理の前に、"success"という文字列を出力するようにしました。
  • Open3.popen3を使用して、別サーバにあるシェルスクリプトを実行し、標準出力・エラーを随時受け取るようにしました。
  • "success"または"already"という文字列を受け取ったら、ループを抜け、リダイレクトするようにしました。

発生している問題

"success"または"already"という文字列を受け取ったら、それに応じたフラッシュメッセージを表示して、リダイレクトできたのですが、"success"を受け取った後、スクリプトが動いているサーバにて、その後の処理が実行されていませんでした。
(該当のソースコード shのecho "success" >&1以降の処理が実行されなかった)。

該当のソースコード

Ruby

1def push_button 2 3 Open3.popen3("ssh hoge bash huga.sh") do |stdin, stdout, stderr, wait_thr| 4 # 標準入力を閉じる。 5 stdin.close_write 6 7 begin 8 received_message = false 9 loop do 10 # .sh実行時のメッセージを受信したらループを抜ける 11 break if received_message 12 # 出力のメッセージを監視 13 IO.select([stdout, stderr]).flatten.compact.each do |io| 14 io.each do |line| 15 if line.include?("success") 16 flash[:success] = "バッチを実行しました。" 17 received_message = true 18 break 19 elsif line.include?("already") 20 flash[:already] = "バッチを実行できませんでした。時間をおいてから、再度お試し下さい。" 21 received_message = true 22 break 23 end 24 next if line.nil? || line.empty? 25 end 26 end 27 # 標準出力、標準エラーでEOFが検知された、つまり外部コマンドの実行が終了したらループを抜ける 28 break if stdout.eof? && stderr.eof? 29 end 30 rescue EOFError 31 end 32 33 redirect_to piyo 34end

sh

1#!/bin/sh 2 3# 二重起動チェック 4CMDLINE=$(cat /proc/$$/cmdline | xargs --null) 5if [[ $$ -ne $(pgrep -oxf "${CMDLINE}") ]]; then 6 echo "already" >&2 7 exit 9 8fi 9 10echo "success" >&1 11 12# やりたい本来のスクリプトの処理 13honsyori

現在の書き方だと、

  • 本処理を実行する前にスクリプトの処理を中断してしまっている?
  • そもそも非同期になっていない?

本件実現するための良い方法があれば、ご教示いただきたいです。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2020/07/31 10:19

> スクリプトの本処理が実行されませんでした。 これはどういう意味ですか? 具体的におねがいします。
nonsuke0113

2020/08/01 05:50

分かりづらく、申し訳ありません。 加筆しました。
guest

回答1

0

ベストアンサー

状況が今ひとつ分かりませんが、"success"がRuby側で受け取れているなら、リモートのシェルスクリプトではhonsyoriが実行されていますので、実行されていないというのが、確認ミスだと思います。

おそらくは、honsyoriの中でエラーが起こって、期待する動作をしていないので、実行されていないと勘違いしたでしょう。

投稿2020/08/01 23:47

otn

総合スコア84499

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nonsuke0113

2020/09/07 07:06

> honsyoriの中でエラーが起こって、期待する動作をしていないので、実行されていないと勘違いしたでしょう。 ご指摘の通りでした。ログ出力される場所の認識が誤っており、実行されていないと勘違いしただけでした。 実際は、honsyori内でエラーが発生し、強制終了していました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問