tty에서 애플리케이션으로 표준 입력 리디렉션

tty에서 애플리케이션으로 표준 입력 리디렉션

이 기사에 대한 후속 조치:쉘 스크립트가 Java를 실행하지 않으며 매개변수가 잘못되었습니다.

콘솔을 읽고 그에 따라 반응하는 프로그램을 Java로 만들었습니다. 이제 이 프로그램을 계속 실행하여 입력된 데이터를 읽으려고 하는데 이 기계에는 입력으로 바코드 판독기만 있습니다. 프로그램을 수동으로 실행하면 제대로 작동하지만 자동화할 수는 없습니다. 키보드나 모니터가 없기 때문에 이것이 필요합니다. 서비스로 실행되면 입력이 허용되지 않으며 /proc/[procid]/fd/0은 항상 권한 거부를 제공합니다.

이 Java 프로그램이 항상 자동으로 다시 시작되고 바코드 판독기의 입력을 읽을 수 있도록 하려면 어떻게 해야 합니까?

바코드 리더는 범용 104버튼 PC(Right-AltGr, 작성 키 없음) 역할을 합니다.

답변1

이 문제를 해결하는 두 가지 주요 방법이 있습니다.

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 세션에서 위 명령을 실행하여 수동으로 시도할 수 있지만 루트로 실행해야 합니다(또는 tty에 대한 권한을 변경해야 합니다). 이 솔루션을 사용할 때 모든 입력을 캡처하려면 tty1에 있어야 합니다(대부분의 시스템에서는 alt+ctrl+F1). 또한 이를 수행하려면 루트(기본적으로 루트임)이거나 실행 중인 사용자에게 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를 강제로 사용할 필요가 없다는 의미이기도 합니다. 그러나 다른 사용자가 직접 액세스할 수 있도록 하려면 여전히 루트로 실행하거나 장치의 권한을 변경해야 합니다.

답변2

부팅 시 프로그램을 시작하고 싶을 수도 있습니다.

이를 수행하는 방법은 다음에 따라 다릅니다.내부에Unix 또는 Linux 시스템에서 사용되는 프로그램(예: 일부 시스템에서는체계다른 사람들은 일부를 사용하고 있습니다.시스템 베넷)

crond시스템에서 부팅하는 경우 @reboot다음을 추가하는 것을 고려하십시오.예약된 작업(5)

이 Java 프로그램이 항상 자동으로 다시 시작되고 바코드 판독기의 입력을 읽을 수 있도록 하려면 어떻게 해야 합니까?

더 나은 접근 방식은 프로그램이 마지못해 멈추지 않을 만큼 충분히 좋은 프로그램을 작성하는 것입니다. 그렇지 않으면 실패 시 다시 시작하도록 일부 쉘 스크립트로 포장하십시오.

Linux에서 바코드 리더를 보는 방법을 알아야 합니다. 아마도 어떤 캐릭터 장치일 수도 있고, 어쩌면 어떤 것일 수도 있습니다.단말기... 바라보다터미널(4),스티티(1),연령(8),용어(3),kbd_mode(1)그리고 읽어보세요Tty가 밝혔습니다.

당신은 또한 볼 수 있습니다이것

서비스로 실행 중인 경우 입력을 허용하지 않으며 /proc/[procid]/fd/0은 항상 권한 거부를 제공합니다.

왜냐하면 이 경우 stdin은 터미널(또는 키보드, 바코드 리더)이 아니기 때문입니다. 아마도 리디렉션해야 할 것입니다.

물론 부팅 시(init, systemd, crontab 등을 통해) 또는 배치 모드( 또는 사용)에서 시작된 프로그램은 at대화 형 명령줄(다른 파일 설명자, 다른 파일 설명 기호)과 동일한 실행 환경을 갖지 않습니다 batch. nohup.환경(7)....). 이러한 프로그램을 작성할 때 이를 고려해야 하거나 일부 래퍼 쉘 스크립트를 작성하여 설정을 멋지게 설정해야 합니다(stdin, stdout, stderr 리디렉션; export- 일부 중요한 변수 지정).

추신. 며칠 동안 Linux에 대해 더 자세히 읽어볼 것을 권장합니다(예:고급 Linux 프로그래밍,부팅에서 Bash 프롬프트까지,리눅스 소개,이해하고 사용하세요systemd,Bash 초보자 가이드) 및 운영 체제(예:운영 체제: 세 가지 간단한 부분) Java 또는 일부 스크립트의 한 줄을 작성하기 전에.

관련 정보