ttyからアプリケーションへの標準入力リダイレクト

ttyからアプリケーションへの標準入力リダイレクト

この記事のフォローアップ:シェルスクリプトはJavaを実行せず、パラメータが無効です。

コンソールを読み、それに応じて反応するプログラムをJavaにしました。今度はこのプログラムを実行し続けて入力されたデータを読み取ろうとしますが、このマシンには入力としてバーコードリーダーしかありません。プログラムを手動で実行すると正常に動作しますが、自動化することはできません。キーボードやモニターがないため、これが必要です。サービスとして実行すると、入力は許可されず、/proc/[procid]/fd/0 は常に権限拒否を提供します。

このJavaプログラムが常に自動的に再起動し、バーコードリーダーの入力を読み取ることができるようにするにはどうすればよいですか?

バーコードリーダーは汎用104ボタンPC(Right-AltGr、作成キーなし)として機能します。

ベストアンサー1

この問題を解決する2つの主な方法があります。

ttyからアプリケーションへの標準入力リダイレクト

デフォルトでは、システムはtty1で起動します。そのttyで実行されているgettyを無効にし、その入力をハイジャックして使用できます。まず、システムでgettyを無効にします。

sudo systemctl stop [email protected]
sudo systemctl disable [email protected]

SSHセッションまたは他のgettyでこれを行う必要があります。そうしないと、ログイン情報が失われます。システムについて言及していませんが、systemdの場合はこれが行く方法です。これがうまくいかない場合は、配布文書を確認してください。

/dev/tty1プログラムの標準入力(</dev/tty1最後)にリダイレクトするために、アプリケーションを含むラッパースクリプトを作成する必要があります。/usr/local/bin/rxtxcomm

#!/bin/bash
/usr/bin/java -Djava.library.path=/usr/lib/jni \
  -cp /usr/share/java/RXTXcomm.jar -jar '/foo/bar.jar' </dev/tty1

実行可能にします。

sudo chmod +x /usr/local/bin/rxtxcomm

次に、サービスファイルを更新してこのスクリプトを実行します。サービスを再起動すると、標準入力が/dev/tty1

他のttyセッションまたはsshセッションで上記のコマンドを実行して手動で試すことはできますが、rootとして実行する必要があります(またはttyの権限を変更する必要があります)。このソリューションを使用するときにすべての入力をキャプチャするにはtty1にする必要があります(ほとんどのシステムではalt + ctrl + F1)。また、これを行うには、root(デフォルトではroot)または実行しているユーザーにttyから直接データを読み取る権限が必要です。

直接読む/dev/input/

Linuxのほとんどすべてのデバイスを/devキーボードとして使用できます/dev/input/。このファイルから直接読み取るようにプログラムを変更できます。ファイルは他のファイルのように読み取ることができますが、バイナリデータが生成されるため、文字を入力するにはさらに作業が必要です。

以下は、以下から取得した短いJavaの例です。このスタックオーバーフローの質問

// replace path with path from your system
DataInputStream in = new DataInputStream(
    new FileInputStream("/dev/input/by-id/usb-0430_0005-event-kbd"));
String map = "    abcdefghijlkmnopqrstuvwxyz                                                                                                                                                                                                                                                                ";
// sizeof(struct timeval) = 16
byte[] timeval = new byte[16];
short type, code;
int value;
while (true) {
    in.readFully(timeval);
    type = in.readShort();
    code = in.readShort();
    value = in.readInt();
    System.out.printf("%04x %04x %08x %c\n", type, code, value, 
                                             map.charAt(value>>>24));
}

この方法の利点は、特定のキーボードに接続できることです。したがって、スクリプトを中断することなく他のキーボードを接続することができます。これはシステムのデバッグに役立ちます。これはまた、アプリケーションが正しく機能するためにttyを無効にしたり、特定のttyを強制的に使用する必要がないことを意味します。ただし、他のユーザーが直接アクセスできるようにするには、まだrootとして実行するか、デバイスの権限を変更する必要があります。

おすすめ記事