Сохраните следующее в usbreset.c
/* usbreset -- send a USB port reset to a USB device */
#include
#include
#include
#include
#include
#include
int main(int argc, char **argv)
{
const char *filename;
int fd;
int rc;
if (argc != 2) {
fprintf(stderr, "Usage: usbreset device-filename\n");
return 1;
}
filename = argv[1];
fd = open(filename, O_WRONLY);
if (fd < 0) {
perror("Error opening output file");
return 1;
}
printf("Resetting USB device %s\n", filename);
rc = ioctl(fd, USBDEVFS_RESET, 0);
if (rc < 0) {
perror("Error in ioctl");
return 1;
}
printf("Reset successful\n");
close(fd);
return 0;
}
Выполните следующие команды в терминале:
Скомпилируйте программу:
cc usbreset.c -o usbreset
Получите идентификатор шины и устройства USB-устройства, которое вы хотите сбросить:
lsusb -t
Bus# 4
-Dev# 1 Vendor 0x1d6b Product 0x0001
-Dev# 3 Vendor 0x046b Product 0xff10
Сделайте нашу скомпилированную программу исполняемой:
chmod +x usbreset
Выполните программу с привилегией sudo
; сделайте необходимую замену идентификаторов
и
, найденных при выполнении команды lsusb
:
sudo ./usbreset /dev/bus/usb/004/003
Сброс USB-устройства /dev/bus/usb/004/003
Сброс прошел успешно
Источник вышеприведенной программы: http://marc.info/?l=linux-usb&m=121459435621262&w=2
ПРЕДУПРЕЖДЕНИЕ:эти операции чрезвычайно рискованны, я не даю никаких гарантий, рекомендуется понимать каждый шаг и применять его на свой страх и риск, иначе вы, вероятно, сломаете свою систему и Я не несу ответственности за любой ущерб, возникший в результате его использования.
Я клонировал все серверные диски на локальную виртуальную машину на своей рабочей станции, чтобы попробовать команды, не затрагивая мой исходный сервер, если вы не уверены, что можете сделать то же самое. После обширных исследований и нескольких экспериментов я наконец нашел решение.
Некоторые системы используют systemd в initrd , после монтирования целевого корня он переключает среду systemd так же, как вы делаете с chroot, все службы отключаются, а затем перезапускаются в новой среде.
Мы могли бы воспользоваться этой функцией, чтобы снова изменить корень, сделав это в клонированной среде на другом диске, чтобы снять блокировки, которые система удерживает в старой среде, поэтому вы можете безопасно размонтировать эти точки -, на самом деле это в основном даже не монтируется. Но эта клонированная среда должна гарантировать правильную конфигурацию, чтобы снова запустить сеть и предоставить доступ по ssh. Если этого не произойдет, считайте себя обреченным.
Важно, чтобы у вас был отдельный раздел. Если вы выполняете chroot в каталог внутри другого раздела, а не на само устройство, система все равно может удерживать устройство родительского раздела. не блокировать никак.
Если у вас есть нераспределенное свободное пространство или вы можете уменьшить некоторые разделы, чтобы освободить место для клонированной среды, рекомендуется.Однако, если у вас нет свободного места для хранения, вы можете создать точку монтирования виртуальной памяти, если у вас достаточно памяти. Сетевой раздел не рекомендуется, так как соединение может быть потеряно во время процедуры.
Точку монтирования виртуальной памяти можно создать с помощью tmpfs
, но это приведет к тому, что эта память будет заблокирована в старой среде, и вы не сможете освободить ее без reboot
или kexec
, лучший подход - использовать zram
, помимо создания запоминающего устройства, оно сжимает данные, поэтому, если вы записываете 5G
данных, на самом деле они будут использовать намного меньше, чем память, но все же вам потребуется достаточно памяти.
Например, если 7G
достаточно, вы можете создать его следующим образом:
sudo modprobe zram num_devices=4
echo 7G | sudo tee /sys/block/zram0/disksize
sudo mkfs.ext4 -m0 /dev/zram0
После подготовки необходимых разделов для клонированной среды вот как это будет работать:
mkdir /tmp/sys
sudo mount /dev/zram0 /tmp/sys # or the target device in place of zram0
# mount other separate partitions if required
sudo tar -cpSf - \
--acls --xattrs --selinux \
--exclude '/dev/*' \
--exclude '/run/*' \
--exclude '/sys/*' \
--exclude '/proc/*' \
--exclude '/tmp/*' \
--exclude '/var/tmp/*' \
--exclude '/var/run/*' \
/ |
sudo tar -xvf - \
--acls --xattrs --selinux \
-C /tmp/sys
Перед переключением:
рекомендуется сделать резервную копиюfstab
. sudo cp -a /tmp/sys/etc/fstab /tmp/sys/etc/fstab-
sudo truncate -s0 /tmp/sys/etc/fstab
Если вы собираетесь изменить раздел, в котором какое-либо устройство является swap
памятью, рекомендуется сначала отключить его:
sudo swapoff -a
Затем для выполнения chroot:
sudo mkdir /sysroot
sudo mount --rbind /tmp/sys /sysroot
sudo touch /etc/initrd-release
sudo systemctl --no-block isolate initrd-switch-root
# it will stop all other services (isolate) and call systemctl switch-root /sysroot
Обратите внимание, что не требуется связывать proc
и dev
, как вы обычно делаете при выполнении chroot, systemd сделает это за вас. Вы можете потерять соединение, если вы подождете некоторое время, и оно все еще не сможет подключиться, примите мои соболезнования, вы были потрачены впустую.
Хотя, если вам повезет и вы сможете подключиться сейчас, вы сможете внести желаемые изменения в таблицу разделов.
Важно настроить путь устройства и uuid (blkid
), чтобы они соответствовали новым:
sudo mv /etc/fstab- /etc/fstab
sudo vi /etc/fstab
sudo vi /etc/default/grub
После того, как вы внесли свои изменения, вы можете использовать ту же стратегию, чтобы вернуться к реальному корневому устройству, после чего не забудьте установить загрузчик для новой среды, чтобы восстановить его снова в случае выключения.:
sudo grub2-install /dev/sda # or the intended bootable disk
sudo grub2-mkconfig -o /etc/grub2.cfg
Как только вы снова переключитесь на свои физические устройства,если вы использовали zram
, вы можете освободить память, следуя:
echo 1 | sudo tee /sys/block/zram0/reset
sudo modprobe -r zram
Помните, что вы делаете это на свой страх и риск.