很长时间以来,我家里没有任何网络连接存储,因为它的电网和电力预算不允许这样做。但是现在我有16 TB的网络连接存储,在不使用时完全不使用电源,并根据需要自动启动。
我使用了具有每个端口电源控制的USB集线器。但是即使关闭USB驱动器的运动电源,每个驱动器的寄生耗电量仍约为3瓦,虽然不是很多,但与4个驱动器相比,浪费的功率要多于打开几个顶灯。每时每刻。因此,我也将所有设备都放在了areare后面,以便可以完全关闭电源。
我正在使用systemd自动安装驱动器,并使用uhubctl将其配置为根据需要打开和关闭驱动器的USB端口。这很难解决,但是效果很好。
[Unit]描述= Startech USB集线器端口4PartOf = media-joey-passport.mount [Service] Type = oneshotRemainAfterExit = trueExecStart = / usr / sbin / uhubctl -a on -p 4; / bin / sleep 20ExecStop = / usr / sbin / uhubctl -a off -p 4
在这些单元中,PartOf与Requires和After的组合使systemd在安装驱动器之前启动端口4服务,在卸载驱动器后停止它。这是最难解决的部分。
睡眠20有点不幸,看来驱动器可能要花几秒钟的时间才能使内核看到足够的电量,因此,如果没有休眠,驱动器将无限期地通电。似乎应该有一种方法声明一个附加的依赖关系,并避免需要睡眠?更新:请参阅下面的评论,以获得更好的方法。
闲置约5分钟后,TimeoutIdleSec使其卸载,然后关闭其USB端口的电源。
我决定不自动执行上述操作,而是临时打开继电器5个小时左右,并在需要该窗口时使用存储。这样做的优点之一是,cron工作无法在清晨启动硬盘。
似乎应该有一种方法声明一个附加的依赖关系,并避免需要睡眠?
(实际上,我非常确定.mount单元在任何情况下都会自动依赖于它们的What =设备,但我想只有After =是隐式的,而Requires =不是。)
我认为在.service中使用StopWhenUnneeded = yes会更简单(一旦您在.mount单元中有了前面提到的Requires = dev-disk)。这样的组合也可能更可靠。
附带一提,听起来您有几个几乎相同的&hub-port-X"单位(或者,如果先前的StopWhenUnneeded = true注释建议可行,至少它们将变得几乎相同)。这些可以折叠成一个模板startech-usb-hub @ .service,该模板使用%i代替各处的端口号。
考虑到内核在使用uas'时似乎不允许SAT ATA直通命令,您还可以详细说明如何监视USB驱动器的运行状况吗?司机。
在systemd单元中,此行可能并不意味着您似乎认为这样做:
除非以这种方式对debian补丁进行系统化,否则整个ExecStart =行都不会传递给shell,因此,如果该部分传递给了命令,则可能只是在解析选项上退出。
空行和以"#"开头的行或&#34 ;;"被忽略,可用于评论。
(某些systemd的文档中确实包含使用sh -c和escapingsemicolons的示例,因此自早期版本以来,情况可能已经发生了变化。MultipleExecStart行是运行多个命令的另一种方法。)
但实际上,我举的例子是可行的。您可以在期刊中看到20秒的延迟:
Sep 09 12:32:24 honeybee systemd [1]:正在启动Startech USB集线器端口4 ... Sep 09 12:32:26 honeybee uhubctl [18819]:集线器2-1的当前状态[0409:005a,USB 2.00, 4个端口] Sep 09 12:32:26 honeybee uhubctl [18819]:端口4:0000 offSep 09 12:32:26 honeybee uhubctl [18819]:根据请求发送电源9月9 12:32:26 honeybee uhubctl [18819]:新集线器2-1的状态[0409:005a,USB 2.00,4个端口] Sep 09 12:32:26 honeybee uhubctl [18819]:端口4:0101电源连接[0480:0200] Sep 09 12:32:46 honeybee systemd [1]:启动了Startech USB集线器端口4。
@grawity,我在设备标签上尝试了Requires,但不能避免该问题:
root @ honeybee:/ etc / systemd / system> ls / media / joey / archive-12ls:无法打开目录' / media / joey / archive-12&#39 ;:没有这样的设备9月9日13:33:50蜜蜂systemd [1]:启动Startech USB集线器端口3 ... Sep 09 13:33:50 honeybee uhubctl [23224]:集线器2-1的当前状态[0409:005a,USB 2.00,4个端口] 9月9日13:33 :50 honeybee uhubctl [23224]:端口3:0000关闭9月9日13:33:50 honeybee uhubctl [23224]:已请求发送电源9月9日13:33:50 honeybee uhubctl [23224]:集线器2-1 [0409]的新状态:005a,USB 2.00,4个端口] Sep 09 13:33:50 honeybee uhubctl [23224]:端口3:0101电源连接[1058:25ee] Sep 09 13:33:50 honeybee systemd [1]:启动了Startech USB集线器port 3.Sep 09 13:33:50 honeybee systemd [1]:正在挂载archive-12 ... Sep 09 13:33:50 honeybee systemd [1]:media-joey-archive \ x2d12.mount:退出挂载进程,代码=退出状态= 32Sep 09 13:33:50蜜蜂systemd [1]:media-joey-archive \ x2d12.mount:失败,结果为'退出代码&#39 ;.蜜蜂9月9 13:33:50 systemd [1]:挂载失败rchive-12。
啊,我想我明白了。关闭USB端口后,udev会将磁盘设备文件保留在原位。尝试访问该设备会导致IO错误,然后udev会注意到该设备已消失并删除其文件。 Sosystemd的依赖项可以正常工作,但是可以看到过时的信息。
也许这是udev中的错误,它没有注意到USB端口已关闭。根据udevadm monitor,它似乎根本没有任何内核事件。
我认为可能有不同的解决方法是在关闭电源后从磁盘上添加一个字节,或者udevadm手动触发设备。不幸的是,当这两个操作完成时,内核会自动为USB端口供电。所以我暂时坚持睡觉。
在systemd单元中,此行可能并不表示您似乎认为的那样
不,这就是那个意思。 ExecStart =中的多个命令以单行分隔;令牌已被支持很长时间了。 (尽管它们在逻辑上总是不合逻辑的-例如,如果您有Type = forking,则应该将哪个命令作为守护程序?为什么不改为使用ExecStartPre&#39 ??而是在Type =中oneshot这种用法很好。)
udev将磁盘设备文件保留在原位。尝试访问该设备会导致IO错误,然后udev会注意到该设备已消失并删除其文件
Udev维护/ dev / disk / *符号链接和systemd的.device单元,但是它100%依赖于接收内核的uevents来触发维护。 (因此,实际的/ dev / sd *节点由内核本身通过devtmpfs创建,不再由udev创建。)
因此,这是一个内核问题。 (或者...也许只是uhubctl的工作方式?内核甚至不知道该端口现在已关闭电源吗?我认为它没有,因为uhubctl绕过了整个USB堆栈。)
我想知道如果您尝试使用udevadm trigger -action = remove / sys /< sysfs_path>伪造内核uevent会怎样?断电后。 (或者echo echo> / sys /< sysfs_path> / uevent。)这不会从内核中删除该设备,只是向udev戳一下它应该删除的内容。
啊哈不幸的是。 (即使API可以始终被放大,我也不会屏息...)
@grawity hmm,很有希望,sysfs uvent文件没有触发udev,但是udevadm trigger --action =删除/ sys / class / block / sdb1"确实删除了/ dev / disk / by-label /中的链接,尽管/ dev / sdb1仍然存在。
是的,然后系统对设备的依赖关系就可以正常工作,它会延迟安装,直到驱动器旋转。
嗯,甚至更容易了," udevadm触发器--action = remove / dev / disk / by-label / passport"不需要查找sysfs路径即可执行相同的操作。
[Unit]说明= Startech USB集线器端口4PartOf = media-joey-passport.mount [Service] Type = oneshotRemainAfterExit = trueExecStart = / usr / sbin / uhubctl -a on -p 4ExecStop = / bin / sh -c' uhubctl -a off -p 4; udevadm trigger --action =删除/ dev / disk / by-label / passport ||真实
现在实际上需要/ bin / sh,因为由于标签不存在等导致的udevadm失败等需要忽略。
很难理解集线器端口的服务文件需要知道磁盘的标签,但是由于我不是使用systemd分隔模板而是通过Haskell代码生成这些服务文件,因此很容易扩展到包括那个。
当您提到继电器时,您是指机电设备吗?如果是这样,您是否测量了继电器线圈通电时的电流消耗?
另外,如果手动操作继电器,您会做什么?是否为将来的自动化做好准备?在这种相对低功率的应用中,继电器似乎可以安全地用作常规机械开关。
例如,此继电器https://www.sparkfun.com/products/13815可以通过GPIO端口进行控制,消耗0.6瓦的功率运行,并且可以切换15安培的交流电流。我很乐意将其中的几个用于其他项目。
我的USB集线器实际上是由24V DC供电的,该电源来自我的太阳能充电控制器的负载端口,该端口也由计算机控制进行切换。 Thatline还为我周围的一个更强劲的24V工业继电器供电,该继电器可以切换更多功率,但运行时确实消耗5瓦。我可能会在某个时候将该继电器降级,但是在驱动器运行时多出5瓦并不是什么大问题。
您是否考虑过使用udisksctl关机安全地关闭USB驱动器,然后再关闭其端口的电源?使用与“安全弹出”的机制相同的机制。 GUI选项,我认为这样做会更安全,并且可能会解决计时问题。
@ pabs3,udisksctl关闭电源--block-device / dev / disk / by-label / passport确实会导致udev删除设备文件,但是在这种情况下,它似乎并不比udevadm trigger --action = remove更好,因为systemd在该磁盘运行之前已经将其卸载。
我注意到的唯一区别是,它断开了集线器端口的连接,但打开了电源,因此仍然需要uhubctl来关闭电源。
该文档(在下面引用)对其确切功能有些含糊,但似乎不仅禁用端口,而且在刷新缓存方面比卸载更胜一筹。
关闭电源安排安全卸下驱动器并关闭电源。在操作系统方面,这包括确保没有进程在使用驱动器,然后请求将运行中的缓冲区和缓存提交给稳定的存储。关闭驱动器电源的确切步骤取决于驱动器本身和所使用的互连。对于通过USB连接的驱动器,其结果是将取消配置USB设备,然后禁用其连接的上游集线器端口。请注意,由于某些物理设备包含多个驱动器(例如4合1闪存卡读取器USB设备),关闭一个驱动器的电源可能会影响其他驱动器。因此,执行此操作没有很多保证。通常,结果是驱动器消失了,就像拔掉了一样。
如果我只是通过uhubctl关闭端口,而没有为它删除/ dev节点,那么系统中的某些内容稍后会访问/ dev节点,这会导致I / O错误,从文件系统中删除dev节点,而且还需要重新启动端口,然后重新开发dev节点。 Aka:不能确保可靠地关闭端口电源。例如,在我的系统上,udisksd本身会每隔10分钟唤醒一次磁盘,以进行SMART检查。
当使用udevadm或任何其他工具删除/ dev节点时,如果我认为对dev节点仍然有打开的文件,那么仍然存在无意打开端口/磁盘电源的风险。更糟糕的是,当所有开发节点都被删除并且一个人想要使用uhubctl重新打开端口电源时,系统将不会重新创建开发节点-因为内核从未看到磁盘消失。仅删除了dev节点。
udiskctl实际上可以完成正确的工作:删除磁盘的内核概念,然后删除开发节点。例:
udisks-消息:22:56:40.318:已成功将SCSI命令SYNCHRONIZE CACHE发送到/ dev / sddudisks-消息:22:56:41.088:已成功将SCSI命令START STOP UNIT发送到/ dev / sddudisks-消息:22:56:41.174 :关闭/ dev / sdd的电源-成功写入sysfs路径/sys/devices/pci0000:00/0000:00:08.1/0000:38:00.4/usb6/6-1/6-1.3/6-1.3.1/ 去掉 因此,对我而言,正确的解决方案是使用udiskctl删除开发节点,然后使用uhubctl关闭端口。 用uhubctl上电后,内核将正确地重新创建dev节点。 介于两者之间,无意唤醒磁盘的唯一剩余风险是内核中的所有东西都会破坏整个集线器。 但是uhubctl的主页上列出了所有已知的可用集线器,其中很多便宜。