`apt-get`、`dpkg` 从蓝牙串行端口失败,但从物理连接的控制台成功

`apt-get`、`dpkg` 从蓝牙串行端口失败,但从物理连接的控制台成功

在 Linux 上,是否有一些配置设置或功能可以解释某些命令可以从系统连接的控制台运行,但不能从串行控制台运行?


我在这里发帖是因为远程系统是 RaspberryPi,但我不思考这个问题与此相关。我怀疑它可能会发生在其他 Debian(也可能是其他 Linux)系统上。

当我通过蓝牙串行端口登录到远程系统时,apt-get update一些与包管理相关的命令会产生错误:

Raspbian GNU/Linux 9 raspberry pi rfcomm0
raspberrypi login: pi
Password:
Last login: Mon Dec  3 12:31:11 UTC 2018 on rfcomm0
Linux raspberrypi 4.9.59-v7+ #1047 SMP Sun Oct 29 12:19:23 GMT 2017 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
pi@raspberrypi:~$ sudo bash
root@raspberrypi:/home/pi# apt-get update
Hit:1 http://archive.raspbian.org/raspbian stretch InRelease
Err:1 http://archive.raspbian.org/raspbian stretch InRelease
  Waited for apt-key but it wasn't there
Reading package lists... Done
W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: http://archive.raspbian.org/raspbian stretch InRelease: Waited for apt-key but it wasn't there
W: Failed to fetch http://archive.raspbian.org/raspbian/dists/stretch/InRelease  Waited for apt-key but it wasn't there
W: Some index files failed to download. They have been ignored, or old ones used instead.
root@raspberrypi:/home/pi# 
root@raspberrypi:/home/pi# dpkg -i /var/cache/apt/archives/apt-utils_1.4.8_armhf.deb 
dpkg: unrecoverable fatal error, aborting:
 wait for subprocess dpkg-split failed: No child processes

直接在远程系统控制台上运行相同的命令会产生错误并且它工作不流畅。该板安装了原厂 Raspbian 系统,除了蓝牙设置外,没有任何配置更改。

pi@raspberrypi:~$ who -a
           system boot  1970-01-01 00:00
           run-level 5  2018-12-03 12:29
pi       - tty1         2018-12-03 12:29 00:53         674
pi       - rfcomm0      2018-12-03 13:27   .          1906
pi@raspberrypi:~$ pstree
systemd─┬─avahi-daemon───avahi-daemon
        ├─bluetoothd
        ├─cron
        ├─dbus-daemon
        ├─dhcpcd
        ├─hciattach
        ├─login───bash───sudo───bash   < XXX apt-* works from here
        ├─rfcomm───login───bash        <     but not from here
        ├─rsyslogd─┬─{in:imklog}
        │          ├─{in:imuxsock}
        │          └─{rs:main Q:Reg}
        ├─systemd───(sd-pam)
        ├─systemd-journal
        ├─systemd-logind
        ├─systemd-timesyn───{sd-resolve}
        ├─systemd-udevd
        ├─thd
        └─wpa_supplicant

这是可重现的或其他 RPi。不过,我手头没有备用的 x86 系统来在正版 Debian 系统上进行测试。


编辑:这更疯狂:我尝试使用 strace 追溯问题,但是:

# apt-get install -y openssh-server
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following package was automatically installed and is no longer required:
  libva-wayland1
Use 'apt autoremove' to remove it.
Suggested packages:
  molly-guard monkeysphere rssh ssh-askpass ufw
The following NEW packages will be installed:
  openssh-server
0 upgraded, 1 newly installed, 0 to remove and 114 not upgraded.
Need to get 0 B/301 kB of archives.
After this operation, 833 kB of additional disk space will be used.
E: Waited for /usr/bin/apt-listchanges --apt || test $? -lt 10 but it wasn't there
E: Failure running script /usr/bin/apt-listchanges --apt || test $? -lt 10
# strace apt-get install -y openssh-server
[...]
[long list of system calls]
[...]
munmap(0x74c0d000, 2269184)             = 0
munmap(0x74a56000, 1798144)             = 0
close(3)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

如您所见,从状态 0(成功)退出运行,并且包已正确安装apt-getstrace在“外部”运行strace不起作用?!?


这个问题挫败了我所有的调查。我在/var/log/syslog、/var/log/auth 和journalctl 中都没有看到任何线索。我清理了 APT 缓存以防万一,但错误消息感觉很虚假,让我认为某些子进程无法生成。我怀疑与 PAM 有关的东西,但我不能确定。

答案1

我使用的是带有 Raspbian Stretch 的 Raspberry Pi Zero W。当我sudo apt-get update通过蓝牙串行控制台登录时,我会收到完全相同的Waited for apt-key but it wasn't there错误消息。这让我发疯,直到我发现你上面的帖子。

在 strace 下运行它对我来说效果很好,就像你一样。但是在 strace 下运行 apt-get 是非常不令人满意的,因为 strace 非常嘈杂并且使得无法阅读 apt-get 所说的内容。

使用蓝牙串行控制台,我能够找到 Raspberry Pi 的 WiFi IP 地址,然后通过 ssh 登录到 Raspberry Pi。我能够sudo apt-get update通过 ssh 成功完成。这是该问题的一种可能的解决方法。ssh localhost如果您不想通过 WiFi,也可以使用。

第二种解决方法是通过蓝牙串行控制台登录 Raspberry Pi,然后screen在 Raspberry Pi 上运行。一旦进入screen,我就可以sudo apt-get update通过蓝牙串行控制台正常运行了!

我怀疑终端仿真存在某种问题,但我不确定。当我最初通过蓝牙串口连接到 Raspberry Pi 时,我没有像在screen或下那样看到绿色命令提示符ssh。我们在下面的行中设置蓝牙 rfcomm 串行控制台的方式可能有问题ExecStart=

/etc/systemd/system/rfcomm.service

[Unit]
Description=RFCOMM service
After=bluetooth.service
Requires=bluetooth.service

[Service]
ExecStart=/usr/bin/rfcomm watch hci0 1 setsid /sbin/agetty -8 --noreset -s -w -L rfcomm0 115200 vt100 -a pi

[Install]
WantedBy=multi-user.target

将行更改ExecStart=为以下内容会得到一个漂亮的绿色命令提示符:

ExecStart=/usr/bin/rfcomm watch hci0 1 setsid /sbin/agetty -8 --noclear -s -w -L rfcomm0 115200 linux -a pi

请注意,更改该文件后必须重新启动才能使其生效。做的sudo systemctl reload rfcomm.service似乎还不够。

不幸的是,即使我现在有了一个漂亮的绿色命令提示符,当不在/ /下运行时sudo apt-get update仍然给我带来可怕的错误!Waited for apt-key but it wasn't therestracescreenssh

答案2

waitpid这与 SIGCHLD 信号以及rfcomm setsid getty 上下文中的工作方式有关。我不了解 POSIX 语义、控制终端和信号处理程序,无法获得更具体的信息,但我相信问题很可能可以追溯到如何射频通讯或者设定值正在调用 fork() / waitpid() 和/或(不)处理 SIGCHLD。

我通过对SO问题的这个小程序进行实验得出了这个结论等待进程组时 waitpid() 无子进程错误当从蓝牙串行终端内部(在 [rfcomm setsid getty] 下)运行时,它会显示不同的行为,在 [rfcomm setsid getty screen] 下它会“中断”,而在 [rfcomm setsid getty screen] 下它会“工作”。

// cc -o wp wp.c
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    pid_t pid, wpid;
    int stat;

    if ((pid = fork()))
    {
        printf("PARENT: %d | CHILD: %d\n", getpid(), pid);
        wpid = waitpid(-getpid(), &stat, 0);
        printf("DONE: wpid %d errno %d %m\n", wpid, errno);
    }
    else
    {
        printf("CHILD pid: %d\n", getpid());
        sleep(1);
    }
    return 0;
}

各种命令的失败结果:

  • wp(上面的waitpid测试程序)
    • “完成:wpid -1 errno 10 没有子进程”
  • crontab -e
    • 退出时陷入循环打印“crontab:waitpid()失败等待来自“/ usr / bin / sensible-editor”的PID 20864:没有子进程”
  • apt-get update
    • “等待 apt-key 但它不存在”
  • git clone https://git.savannah.gnu.org/git/screen.git
    • “错误:索引包的 waitpid 失败:没有子进程”
    • 有趣的是,git clone git://git.savannah.gnu.org/screen效果很好。
    • “它在 GNU/screen 下运行时可以工作”让我尝试从 screen 的源代码中找出原因,但我什么也没想到

笔记

  • 登录后,如果您调用 /bin/dash,则所有命令都可以正常工作,类似于它们在屏幕下的工作方式,尽管运行 /bin/bash 或 /bin/bash --login 没有帮助。
  • waitpid 测试在使用破折号“启用作业控制”参数 -m 运行时有效,如下所示:/bin/dash -m -c "~/src/wp/wp"

我想排除是否涉及“控制 TTY”,因为这会影响信号,并且我看到 rfcomm 在 open()ing /dev/rfcomm0 时使用 O_NOCTTY 标志。实验setsid --ctty显示出更糟糕的行为,而且我还没有尝试改变rfcomm.c 源代码。我正在(重)读TTY 揭秘作者:Linus Akkeson,试图了解更多。

我意识到这不是一个答案,SE 也不是一个论坛,但我希望这对某人有帮助,并且没有足够的声誉来发表评论。

相关内容