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

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

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

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

6529閲覧

Node.jsからシェルスクリプトを実行して標準入力でデータを渡したい

退会済みユーザー

退会済みユーザー

総合スコア0

bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2018/01/15 09:35

###前提・実現したいこと
pythonからシェルスクリプトを実行するコードをNode.jsで書き直すことになりました。
シェルスクリプトには標準入力でJSONを渡しています。
以下のページを参考にしました。
https://nodejs.org/docs/latest-v8.x/api/child_process.html#child_process_child_process_spawn_command_args_options
https://nodejs.org/docs/latest-v8.x/api/stream.html#stream_writable_write_chunk_encoding_callback

###発生している問題・エラーメッセージ
標準入力を渡さない場合はシェルスクリプトが意図した通りに実行されました。
標準入力でシェルスクリプトにデータを渡そうとすると上手くいかず、下記のエラーメッセージが表示されるようになりました。
なぜか偶にエラーにならず実行されることもありますが、その場合はシェル側で標準入力が取得できず、標準入力を渡さず実行した場合と同じ結果になりました。

events.js:183 throw er; // Unhandled 'error' event ^ Error: write EPIPE at _errnoException (util.js:1022:11) at WriteWrap.afterWrite [as oncomplete] (net.js:867:14)

###該当のソースコード
$ node test.jsで実行しています。

javascript

1// test.js 2const path = require('path') 3const spawn = require('child_process').spawn 4 5const script = path.resolve(__dirname, 'path', 'to', 'script') 6const data = { 7 name: 'foo', 8 age: 999 9} 10 11const child = spawn(script) 12child.stdin.write(JSON.stringfy(data), 'utf8') 13child.stdin.end()

ちなみにpythonでは以下のようなコードで、意図した通りの動作が確認できました。

python

1from os import path 2import subprocess 3import json 4 5SCRIPT = path.join( 6 path.dirname(path.abspath(__file__)), 7 'path', 'to', 'script' 8) 9DATA = { 10 name: 'foo', 11 age: 999 12} 13 14subprocess.run( 15 [SCRIPT], 16 input=json.dumps(DATA).encode('utf-8'), 17 check=True 18)

シェルスクリプトは以下のような感じです。直接実行してもpythonから実行しても問題ないので標準入力の受け取り方に問題があるとは思えませんが、念のため載せておきます。

bash

1#!/bin/bash 2 3if [ ! -p /dev/stdin ]; then 4 # 標準入力から何も渡ってこない場合はエラー 5 exit 1 6fi 7 8# 実行したい処理 9do_something -r '...' < /dev/stdin | # 続く...

###試したこと
child.stdin.write()の戻り値を調べるとtrueでした。callbackも引数に渡すと、それが実行された上で上記のエラーが発生するようです。
spawn(script)spawn('cat') にしてchild.stdout.on('data', data => console.log(data))で標準出力を表示したら、エラーは発生せずに標準入力に渡したJSONがそのまま表示できました。

###補足情報(言語/FW/ツール等のバージョンなど)
OS: Ubuntu16.04
Node.js: v8.9.4

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

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

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

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

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

guest

回答1

0

ベストアンサー

catに標準入力を流すことは出来ていたので、シェルスクリプトでの標準入力の受け取り方を以下のように修正しました。

diff

1-if [ ! -p /dev/stdin ]; then 2- # 標準入力から何も渡ってこない場合はエラー 3- exit 1 4-fi 5 6 # 実行したい処理 7-do_something -r '...' < /dev/stdin | # 続く... 8+cat | do_something -r '...' | # 続く...

どうやらシェルスクリプトの中で/dev/stdinを扱おうとすると問題があるみたいで、リダイレクトで読み込めないだけでなくガード節でテストするだけでも上述のエラーが発生してしまうようです。

一応解決策が見つかりましたが、なぜnodeから実行すると/dev/stdinがダメなのか分かる方は教えていただけると有難いです。

投稿2018/01/16 04:21

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問