我有一个 USB 设备,我希望自动重置,当前有两个 USB 设备,但有时可能会有更多。
[user1@gs10 devt]$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 007: ID 1604:10c0 Tascam Dell Integrated Hub
注意事项:
- 设备编号会定期更改(固件问题(我这边))
- 当插入不同的 Tascam Hub 时,ID 将是动态的
- 字符串也可能会改变,空格,破折号。
我要重置的设备是Device 007。我识别设备ID的方法如下:
[user1@gs10 devt]$ lsusb | grep "Tascam" | awk '{printf $6 "\n"}'
1d6b:0003
工作正常。现在我想将内核的 usbreset 命令作为单行命令运行,而无需手动输入供应商 ID,有什么建议吗?
我的尝试和目标:
lsusb | grep "Tascam" | awk '{printf "/usr/bin/usbreset %d", $6}'
[user1@gs10 devt]$ sudo /usr/bin/usbreset 1d6b:0003
答案1
一种选择是system()
直接从内部使用awk
:
1. 验证
通过从以下位置请求设备进行验证lsusb
:
lsusb | awk '/Tascam.*Hub$/{ system("lsusb -d " $6) }'
这将从匹配的整行中获取vendor:product
, (字段 6):
Tascam<Anything zero or more times>Hub<END-OF-LINE>
并执行:lsusb -d vendor:product
这将执行于全部匹配 Tascam 轮毂。
2.真实通话
实际上调用usbreset
:
lsusb | sudo awk '/Tascam.*Hub$/{ system("/usr/bin/usbreset " $6) }'
或者也许更好,如果出现错误则退出:
lsusb | sudo awk '/Tascam.*Hub/{ if (system("/usr/bin/usbreset " $6)) exit 1 }'
作为system(expression)
返回命令的退出状态,如果0
成功,可以使用它if ()
来检查状态是否为<> 0,它将继续exit 1
。用其他东西退出然后0
发出错误信号。
!= 0
如果您发现更容易阅读,则可以选择使用。也许会抛出一个错误。
lsusb | sudo awk '
/Tascam.*Hub/ {
if (system("/usr/bin/usbreset " $6) != 0) {
print "usbreset failed" >"/dev/stderr"
exit 1
}
}'
3. 设备上的包装器+过滤器
如果你想筛选根据设备号,最好将其包装在 shell 脚本中(无论如何您都可能会这样做),然后执行以下操作:
#! /bin/sh -
# Check argument is given
if [ -z "$1" ]; then
printf 'Missing device number\n' >&2
exit 1
fi
# Check sudo or abort
sudo echo >/dev/null || exit 1
lsusb |
sudo awk -v dev="$1" '
BEGIN {
dev = sprintf("%03d:", dev)
eno = 1
}
$4 == dev && /Tascam.*Hub/ {
if (system("/usr/bin/usbreset " $6) != 0) {
eno = 2
} else {
eno = 0
}
# Exit on first match of device-number + name
exit
}
END {
if (eno == 0)
print "OK"
else if (eno == 1)
print "No device found" >"/dev/stderr"
else if (eno == 2)
print "usbreset failed" >"/dev/stderr"
exit eno
}'
注意事项usbreset
无法在本地安装它,但看起来有些人将参数视为:
/dev/bus/usb/<bus>/<device-number>
在这种情况下,你可能需要使用类似的东西:
# Testing:
system(sprintf("ls -l /dev/bus/usb/%03d/%03d", $2, $4))
# Testing:
system(sprintf("/usr/bin/usbreset /dev/bus/usb/%03d/%03d", $2, $4))
4.有关问题的注意事项:
grep
awk
下一步是什么时候是一个不必要的步骤。awk
匹配正则表达式 - 在本例中它是一个简单的字符串(在您的代码中)。
awk '/^foo/{ this line starts with foo }'
ETC。
printf $6 "\n"
看起来你想打印$6
+换行。那将是:
print $6
printf "%s\n", $6
它还告诉 awk 用作$6
格式字符串。这可能会变得很糟糕,而且通常不是一件好事。$6
例如,如果是foo%dbar
,awk 会期望一个数字作为参数。 ETC。
printf "/usr/bin/usbreset %d", $6
, 说“打印数字”这里的值是“6 美元”。由于字段 6hex:hex
是打印函数语句将只打印第一个数字(如果有),否则为零。
12a1:06df
->12
a112:3619
->0
答案2
听起来这可能就是您想要做的:
$ cat file | awk '$7=="Tascam"{print $6}' | xargs echo sudo /usr/bin/usbreset
sudo /usr/bin/usbreset 1604:10c0
或者:
$ echo sudo /usr/bin/usbreset "$(cat file | awk '$7=="Tascam"{print $6}')"
sudo /usr/bin/usbreset 1604:10c0
当您对输出感到满意并且想要实际执行当前回显的命令时,替换cat file
为lsusb
并删除。echo