시리얼을 통해 로그인하도록 getty를 설정하려고 합니다(주로 실험용).
거의 모든 구성에서 동일한 현상이 발생합니다. 기본 쉘이 이면 bash
로그인 후 다음 메시지가 표시됩니다.
-bash: cannot set terminal process group (15297): Inappropriate ioctl for device
-bash: no job control in this shell
그런 다음 작동하지 않는다는 것을 증명하기 위해 Ctrl+C를 사용하여 프로그램을 중지할 수 없습니다.
$ sleep 30
^C
그리고 아무런 신호도 전송되지 않는 것 같습니다.
내가 시도한 구성은 다음과 같습니다.
나는이 두 명령을 시도했습니다
# copied from raspberry pi:
sudo /sbin/agetty --keep-baud 115200,38400,9600 ttyUSB0 vt220
# something else I read somewhere
sudo getty -L ttyUSB0 9600 vt100
# (I know I'm mixing and matching a lot of differences but the result is the same)
저는 screen과 picocom을 클라이언트로 사용해 보았습니다.
나는 rasberry pi를 서버로 사용하고 두 개의 다른 우분투 랩탑을 사용해 보았습니다.
저는 2개의 FTDI, 2개의 RS-485 USB 어댑터, 게티 측의 내장 RS232, 클라이언트 측의 USB RS232를 사용해 보았습니다.
또한 기본 셸을 sh 및 dash로 변경해 보았습니다. 메시지를 받지 못했지만 Ctrl+C가 여전히 예상대로 작동하지 않습니다.
흥미로운 점은 Raspberry Pi가 자동 구성하고 /dev/ttyAMA0
내가 입력한 getty 명령을 정확하게 사용하면 작업 제어가 작동한다는 것입니다!
그리고 터미널 설정도 거의 동일합니다. (실제로는 -iutf8을 제외하고)
FTDI 연결 및 picocom 실행을 위한 터미널 설정은 다음과 같습니다.
$ stty -a -F /dev/ttyUSB0
speed 9600 baud; rows 24; columns 80; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D;
eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q;
stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
lnext = <undef>; discard = <undef>; min = 1; time = 0;
-parenb -parodd -cmspar cs8 hupcl -cstopb cread clocal
-crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr
-icrnl ixon ixoff -iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0
tab0 bs0 vt0 ff0
isig -icanon -iexten -echo echoe echok -echonl -noflsh -xcase
-tostop -echoprt echoctl echoke -flusho -extproc
$ stty -a -F /dev/ttyUSB1
speed 9600 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D;
eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q;
stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V;
discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 hupcl -cstopb cread clocal
-crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr
-icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0
cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo echoe echok -echonl -noflsh -xcase
-tostop -echoprt echoctl echoke -flusho -extproc
내가 뭘 잘못했나요? Raspberry Pi에 내장된 직렬 포트의 내장 구성에서 작동하는 이유는 무엇입니까?
답변1
차이점은 명령에 있는 것이 아니라 명령이 실행되는 환경에 있습니다.
일반적으로 getty는 시스템 서비스 관리자(init)에서 직접 생성됩니다. systemd에서는 .service이고 SysV 세계에서는 inittab 항목이 있습니다(init.d 스크립트가 아닙니다!). 이것과 다른 터미널에서 생성되는 것 사이에는 몇 가지 차이점이 있습니다.
첫째, 터미널에서 시작된 프로세스는 이를 자신의 자산으로 상속받습니다."제어 터미널",이는 쉘 작업 제어의 가장 중요한 매개변수입니다. ps aux
or - 서비스 프로세스 ps -ef
에서 이를 볼 수 있으며 처음에는 ctty가 없으므로 getty가 표시된 터미널을 열 때 쉘이 실행되면 해당 터미널이 작업 제어를 위한 제어 터미널이 됩니다.
그러나 xterm에서 시작된 getty는 입력/출력이 이제 직렬 포트로 라우팅되지만 xterm pty를 제어 tty로 계속 유지합니다. getty 자체는 신경 쓰지 않지만 쉘은 그렇지 않습니다.반품잘못된 제어 tty를 상속받으면 작업 제어가 불가능해집니다.
$ ps -C agetty
PID TTY TIME CMD
1136 tty1 00:00:00 agetty
14022 pts/22 00:00:00 agetty
^-- should be ttyS0!
제어 터미널은 /dev/tty를 정의하고, 작업 제어 신호가 전송되는 프로세스를 정의하며, 터미널이 닫힐 때 종료될 프로세스(SIGHUP)를 정의합니다. 쉘이 stdin/out tty와 다른 제어 tty를 상속받는 경우 모든 종류의 이상한 일이 발생할 수 있습니다.
프로세스는 setid() 호출과 같은 여러 가지 방법으로 이전 터미널에서 분리될 수 있습니다. 전통적으로 /etc/init.d 스크립트는 프로세스를 "데몬화"하기 위해 이 작업을 수행하지만 getty는 자동으로 이를 사용하지 않습니다.예상치 못한이런 식으로 실행되므로 프로그래밍되지 않습니다. ( setsid
이런 일이 발생하도록 강제로 사용할 수 있는 도구 가 있지만해서는 안 된다여기에서도 사용할 수 있습니다. 처음부터 올바른 방식으로 작업을 수행해야 합니다. )
이상적으로는systemctl start serial-getty@ttyUSB0
getty를 깨끗한 환경에서 실행해 보세요. 사용자 정의 옵션이 필요한 경우 systemctl edit [--full]
getty를 직접 실행하는 것보다 서비스를 사용자 정의하는 것이 좋습니다 . (systemd를 사용하지 않는 경우 편집하세요 /etc/inittab
. 일반적으로 예제가 포함되어 있습니다. telinit q
inittab을 다시 로드하려면 실행하세요.)
쉘에서 시작된 프로세스와 서비스 관리자를 통해 시작된 프로세스 사이에는 상대적으로 사소한 차이점이 많이 있습니다. stdin/stdout/stderr은 터미널로 먼저 시작됩니다(getty는 프로세스를 닫았다가 다시 열지만 모든 서비스가 이 작업을 수행하는 것은 아닙니다). 변수는 "sudo"에서 상속되며, 이는 cgroup의 리소스 제한에 영향을 미칠 수 있으며, systemd-logind 세션은 상속되며 SELinux 보안 컨텍스트를 시작할 수 없습니다. (또는 AppArmor 프로필 또는 SMACK 태그)이 상속됩니다(사용 중인 경우).