/etc/rc.local(通过 systemd 运行)在 cat'ing /dev/urandom 时挂起

/etc/rc.local(通过 systemd 运行)在 cat'ing /dev/urandom 时挂起

我创建了一个/etc/rc.local

$ cat /etc/rc.local 
#!/bin/bash

echo "Starting"
randomString=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1`
echo "Finished"

在以交互方式运行时,它将运行:

$ /etc/rc.local 
Starting
Finished: lkFcvByNaIu7zmxuCYB3BQmJ05LwuVWL

但是,当从 systemd 运行时它会挂起并且不会返回。

如果我按 ctrl+C 它看起来就像挂在fold命令处:

$ systemctl status rc-local
● rc-local.service - /etc/rc.local Compatibility
   Loaded: loaded (/lib/systemd/system/rc-local.service; enabled-runtime; vendor preset: enabl
  Drop-In: /lib/systemd/system/rc-local.service.d
           └─debian.conf
   Active: activating (start) since Mon 2019-03-11 12:04:06 UTC; 12s ago
     Docs: man:systemd-rc-local-generator(8)
Cntrl PID: 936 (rc.local)
    Tasks: 5 (limit: 1152)
   CGroup: /system.slice/rc-local.service
           ├─936 /bin/bash /etc/rc.local start
           ├─952 /bin/bash /etc/rc.local start
           ├─953 cat /dev/urandom
           ├─954 tr -dc a-zA-Z0-9
           └─955 fold -w 32

Mar 11 12:04:06 ip-10-0-4-116 systemd[1]: Starting /etc/rc.local Compatibility...
Mar 11 12:04:06 ip-10-0-4-116 rc.local[936]: Starting
$ ps -ef
root       936     1  0 12:04 ?        00:00:00 /bin/bash /etc/rc.local start
root       952   936  0 12:04 ?        00:00:00 /bin/bash /etc/rc.local start
root       953   952 47 12:04 ?        00:00:23 cat /dev/urandom
root       954   952 36 12:04 ?        00:00:18 tr -dc a-zA-Z0-9
root       955   952 10 12:04 ?        00:00:05 fold -w 32

解决方法(某种程度上)

我其实不需要非常随机字符串,因此我可以使用:

date | md5sum | cut -c -12

生成一个字符串。当由 systemd 运行时,此命令运行良好。但了解上一个命令为何会挂起会很有趣。

答案1

担!

恕我直言,猫/ dev / urandom注定会永远存在,所以你应该先使用命令读取八十行随机内容,然后关闭输入。

使用简单的头部-80你仍然有多余的角色没有使用,但它不应该永远停滞,因为它正在关闭/dev/urandom80 个换行符(或 CRLF)之后。这是一个丑陋的 hack:

$ cat /etc/rc.local 
#!/bin/bash

echo "Starting"
randomString=`head -80 /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1`
echo "Finished"

我认为后台任务中的行为有所不同,因为 systemd 不知道什么时候会/dev/urandom完成从随机数设备读取。看起来一样,但显然不一样。您的脚本依赖于在最后一个 head 命令完成后断开管道,因此不可靠,无法移植。它还可以以“Broken Pipe”信号结束,表示管道中的前一个命令已捕获并处理。在 systemd 运行的 init 脚本中可能没有提供此类通信和猫/ dev / urandom由于未收到信息而挂起信号管道信号或者别的什么...

希望这可以帮助。

这不保证范围内有 32 个字符[A-Za-z0-9],但重点是结束/dev/urandom而不是依赖信号管道magic 来终止在没有控制终端的情况下在后台无法正常工作的进程。

您还可以执行以下操作:

randomString=`head -80 /dev/urandom | md5sum | cut -c -12`

就像你的第二个例子一样。它是随机的/dev/urandom

相关内容