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

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

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

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

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

リダイレクト

プログラムの入力元や出力先を通常とは別の場所に転送させることをリダイレクトと呼びます。

Q&A

1回答

1975閲覧

node.jsでStreamを使用したプログラムが終了しない

saoka

総合スコア0

Node.js

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

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

リダイレクト

プログラムの入力元や出力先を通常とは別の場所に転送させることをリダイレクトと呼びます。

0グッド

0クリップ

投稿2020/09/05 10:27

編集2020/09/05 11:09

前提・実現したいこと

OS:Linux
言語:node.js

上記環境でmkfifoコマンドにより作成した名前付きパイプに書き込んだ文字列を
指定の端末およびログファイルにリダイレクトするプログラムを作成したいと思っています。

発生している問題・エラーメッセージ

端末およびログファイルへのリダイレクトは上手くいくのですが
プログラムが終了せず、Ctrl+Cで強制終了するしかない状態です。
プログラムを正常終了させる方法を教えていただけないでしょうか。

該当のソースコード

node

1const fs = require('fs'); 2const stream = require('stream'); 3 4const PIPE = 'mkfifoで作成した名前付パイプのパス'; 5const TTY = 'ttyコマンドで取得したパス'; 6const LOG = 'ログファイルのパス'; 7 8async function wait(msec) { 9 return new Promise((resolve, reject) => setTimeout(() => resolve(), msec)); 10} 11 12!async function main() { 13 // パイプ書込/読込ストリーム 14 const writer = fs.createWriteStream(null, {fd:fs.openSync(PIPE, 'w+')}); 15 const reader = fs.createReadStream (null, {fd:fs.openSync(PIPE, 'r+')}); 16 // 端末書込ストリーム 17 const tty = fs.createWriteStream(null, {fd:fs.openSync(TTY, 'w')}); 18 // ログ書込ストリーム 19 const log = fs.createWriteStream(null, {fd:fs.openSync(LOG, 'a')}); 20 // ストリーム分岐用 21 const hub = new stream.PassThrough(); 22 const wire1 = new stream.PassThrough(); 23 const wire2 = new stream.PassThrough(); 24 25 // ストリームを以下のように接続 26 // reader ---> hub ---> wire1 ---> tty 27 // ---> wire2 ---> log 28 reader.pipe(hub); 29 hub.pipe(wire1).pipe(tty); 30 hub.pipe(wire2).pipe(log); 31 32 // パイプに書き込み 33 writer.write('hello\n'); 34 35 // 1秒待機 36 await wait(1_000); 37 38 // 終了処理 39 console.log('----- EXIT -----'); 40 41 reader.push(null); 42 reader.read(0); 43 44 writer.end(); 45 writer.close(); 46 47 tty.end(); 48 tty.close(); 49 50 log.end(); 51 log.close(); 52}(); 53

試したこと

  • main()の末尾でprocess.exit()を実行してもプログラムが終了しませんでした。
  • await wait(1_000);をコメントアウトすると、プログラムは終了するのですがリダイレクトされませんでした。

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

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

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

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

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

guest

回答1

0

端末およびログファイルへのリダイレクトは上手くいくのですが

(中略)
プログラムを正常終了させる方法

Promise を使った wait() 関数の引数(msec)は {number} のはずです。
1_000 を与えているので、エラーとなり、 reject() されていないのでは?

javascript

1async function wait(msec) { 2 return new Promise((resolve, reject) => { 3 try { 4 setTimeout(() => resolve(), msec)); 5 } catch( e ) { 6 reject(e) 7 } 8}

試しに、1_000 を与えて setTimeout を実行した例

javascript

1setTimeout(() => { 2 console.log("test timeout") 3}, 1_000); 4// => Uncaught SyntaxError: Invalid or unexpected token

投稿2020/09/05 23:29

AkitoshiManabe

総合スコア5432

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

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

saoka

2020/09/06 02:56

回答ありがとうございます。 数値中のアンダースコアはnumeric separatorという機能で まだ正式採用されていないのかもしれませんが 私の環境では 1_000 は number として認識されているので大丈夫だと思います $ node --version v14.9.0 $ node -e 'console.log(typeof 1_000)' number
AkitoshiManabe

2020/09/06 09:54 編集

> numeric separatorという機能 これは、勉強になりました。ありがとうございます。 ご質問のコードは試していないのですが、Stream 関連のドキュメントを読んで感じた2点: 1. fs.createReadStream() / fs.createWriteStream() は第一引数に PATH を与え、read/writeのバッファに直接作用させても良いのではないか?(オプションでfh のフラグを指定) 2. コールバック方式で利用し、 Promise 化を考える( stream.end() や stream.close() は処理を強制するので 1秒で終わらない長いストリームは、異常終了しないかと感じました)。 async await を使うとコードは短くて見通しが良さそうになりますが、公開される各モジュールは旧バージョンへの対応もあってか、「泥臭い方法」が多いようです。 解決に至る回答はできませんでしたが、参考になればと思います。
saoka

2020/09/07 00:18

さらなる回答ありがとうございます。 ご指摘いただいた方法でも試してみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問