【问题标题】:systemd: start service at boot time after network is really up (for WoL purpose)systemd:在网络真正启动后在启动时启动服务(用于 WoL 目的)
【发布时间】:2016-06-18 17:41:53
【问题描述】:

我有一台工作的计算机,有时我会从家里醒来以访问它,但是当启动并从我们的 DHCP 服务器获取另一个 IP 地址时,我该如何访问它?

情况和我的“工作流程”如下:

  • 我从家里的 PC 连接到办公室的 VPN
  • ssh 到办公室局域网中的专用服务器(它有一个固定的 IP 地址)
  • 在该服务器上,我调用了一个脚本,该脚本使用我办公室 PC 的 MAC 地址广播一个 WoL 数据包
  • 我的办公室 PC 启动(确实如此,当然!)

现在理论上,只要我知道它的 IP 地址,我就可以通过 SSH 连接到我的办公室 PC。 有时它会变得相同,有时它会改变。 为了规避这一点,我有以下想法:

  • 启动我的办公室 PC 后,通过 SSH 连接到办公室服务器,并将其自己的 IP 地址写入服务器上的某个文本文件中
  • 我检查了服务器上的那个文件(我可以连接到它,因为它的 IP 固定),找到我的办公室 PC 的 IP 地址,然后可以从我的家庭 PC SSH 到我的办公室 PC

所有计算机都运行 Linux;家里的 Ubuntu 14.04,办公室服务器上的 SLES,我办公室 PC 上的 OpenSUSE 13.1。这都不是问题。

为了使这一切正常工作,我只需要在我的办公室 PC 上运行一个脚本,该脚本在启动时运行当网络启动并运行时

我的脚本(publish_ip.sh)如下:

# get own IP address:
ip=$(ip addr show | awk '$1=="inet" && $2 !~ /127\.0\.0\.1/ { split($2, a, "/"); print a[1]}');

# SSH to the office server (10.64.5.84) and write own IP address to a file there:
ssh -x -e none 10.64.5.84 "echo $(date) $ip >> office_pc_address.txt"

为了在启动时运行此脚本,我为我的办公室 PC 创建了一个 systemd 服务文件 publish-ip.service:

[Unit]
Description=publishes own IP address
Wants=network.target
After=network.target

[Service]
Type=oneshot
ExecStartPre=/usr/bin/sleep 30
ExecStart=/home/perldog/bin/publish_ip.sh
User=perldog

[Install]
WantedBy=multi-user.target

但这是我在办公室电脑上经常看到的:

linux-tz7m:/usr/lib/systemd/system # systemctl status publish-ip.service
publish-ip.service - publishes own IP address
   Loaded: loaded (/usr/lib/systemd/system/publish-ip.service; enabled)
   Active: failed (Result: exit-code) since Mon 2016-02-29 12:17:34 CET; 4 days ago
  Process: 1688 ExecStart=/home/perldog/bin/publish_ip.sh (code=exited, status=255)
  Process: 1016 ExecStartPre=/usr/bin/sleep 30 (code=exited, status=0/SUCCESS)
 Main PID: 1688 (code=exited, status=255)

Feb 29 12:17:34 linux-tz7m publish_ip.sh[1688]: ssh: connect to host 10.64.5.84 port 22: Network is unreachable

显然我的服务启动并调用了我的脚本,但该脚本中的 SSH 命令失败并显示Network is unreachable

我尝试了我的服务文件中的所有内容,以便它仅在网络启动后运行,但我不明白。我试过Wants=network.targetAfter=network.targetWantedBy=multi-user.target,甚至插入了ExecStartPre=/usr/bin/sleep 30。没有任何效果。 当我的脚本被调用并尝试通过 SSH 连接到办公室服务器时,我总是得到 Network is unreachable

问题:我的服务文件需要哪些设置才能使其仅在可以通过 SSH 访问办公室服务器后运行?

注意:当我在办公室并且我的办公室电脑启动并运行时,我的脚本和服务都可以正常运行,即systemctl start publish-ip.service 工作没有任何错误。

【问题讨论】:

标签: linux networking ssh systemd


【解决方案1】:

您可以通过将 ping 循环添加为 ExecStartPre 脚本来延迟作业的开始:

[Service]
   ExecStartPre=/bin/sh -c 'until ping -c1 google.com; do sleep 1; done;'

Found here

【讨论】:

  • 我在这里尝试了所有解决方案,尽管它看起来很老套,但这确实有效。谢谢
【解决方案2】:

我尝试了所有这些目标,它们都在 DHCP 获得 IP 地址之前到达。去图:

  • network-online.target
  • remote-fs.target
  • nfs-client.target
  • dbus.service

起作用的是启用这两个:

systemctl enable systemd-networkd.service systemd-networkd-wait-online.service

然后设置

After=systemd-networkd-wait-online.service
Wants=systemd-networkd-wait-online.service

现在它开始 DHCP 获得一个 IP 地址之后。 (一个mount point in my case,但也可以是你的服务)

(在 debian9/stretch 上)

【讨论】:

  • 你会在哪里添加你发布的两行?如何让 systemd-networkd-wait-online.service 在启动时启动?增加的两行就够了吗?
  • 我不记得了,我已经离开了那份工作,但我想我只是把它放在 .service 或 .mount 文件中。请点击我的其他帖子的链接以获取更多信息。
【解决方案3】:

不是一个完整的解决方案,但我在计算机启动后设置了一个 SSH 隧道;它每 5 秒重新启动一次,以防止在网络仍然关闭时因发送垃圾邮件而被杀死;如果您可以将固定 IP 系统用作堡垒主机,则可以将这样的东西与您的 WOL 配对使用:

[Unit]
Description=Keep open a reverse tunnel to my home server
After=network.target

[Service]
ExecStart=/usr/bin/ssh -NT hometunnel
RestartSec=5
Restart=always

[Install]
WantedBy=multi-user.target

root 的 .ssh/config 的相关部分:

Host                    hometunnel
HostName                <redacted>
IdentityFile    /root/.ssh/<redacted>
User                    <redacted>
RemoteForward   <redacted> localhost:22
ExitOnForwardFailure yes
ServerAliveInterval 60
ServerAliveCountMax 5

【讨论】:

【解决方案4】:

曾经有一个名为 arpwatch 的工具,它记录所有联网设备的 IP 地址和 MAC 地址,因此您可以简单地 grep 查找计算机的 MAC 并获取 IP。

还有一个叫arping的工具,你可以通过grep查看MAC地址的输出。

另一种选择是在您的计算机上保持一个随机端口打开并使用 nmap 扫描整个网络以查找该特定端口,或者对整个网络进行 nmap 以查找已启动的主机并 grep 获取您的 MAC 地址...

nmap -sP 192.168.1.0/24

【讨论】:

  • 谢谢,但是我的办公服务器上没有安装 arpwatch、arping 和 nmap。 :-( 我已经搜索了 “如何从 MAC 地址获取 IP 地址” 但没有结果。这就是为什么我有我的方法的想法。我承认它非常复杂。
  • @PerlDog,根据您的评论,ARP 是将第 3 层(IP)地址转换为第 2 层(MAC 地址),这听起来与您想要的相反。假设主机使用 DHCP 分配其 IP 地址,您可以在一个地方查看 MAC 地址到 IP 地址,那就是 DHCP 服务器。
  • @RonMaupin 谢谢,但我尝试了所有ping -b 10.64.255.255; arp -na | grep $MAC 的建议。他们都没有工作,我很确定我没有对我们网络中的 DHCP 服务器的“查询”访问权限(我是非 root 用户)。所以这个 publish-ip-script 出现在我的脑海中,但这也不起作用:-(因为它在网络启动之前运行。
  • @PerlDog,IP 和以太网从未设计用于 LAN 发现。您可以获得具有您需要的东西的源(DHCP 服务器)。许多主机现在都有防火墙,可以而且经常会阻止 ping 和其他可能用于 LAN 发现的东西。带有连接到有线以太网交换机的软件防火墙的静态分配主机在 LAN 上几乎是不可见的。您可以有一个应用程序为 LAN 上的每个可能的 IP 地址发送 ARP 请求,但这可能是非常多的地址并且需要很长时间。
  • @RonMaupin 当然。为了避免这种情况,我的脚本开始了。如果你愿意,它有点像穷人的 DynDNS,即它将 IP 发布到一个众所周知的位置。我想我应该改写我的问题(或发布一个新问题),以便它更加强调 systemd/network up 问题。我写了所有这些东西,因为我想避免XY problem
猜你喜欢
  • 1970-01-01
  • 2020-05-11
  • 2019-06-18
  • 2016-11-10
  • 1970-01-01
  • 2021-01-08
  • 2015-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多