Как выполнить ту же операцию, что и нажатие кнопки извлечения в nautilus, выполнив команду?

Вы можете настроить порт управления и использовать скрипт python

from stem import Signal
from stem.control import Controller

with Controller.from_port(port = 9051) as controller:
    controller.authenticate()
    controller.signal(Signal.NEWNYM)
2
задан 21 July 2017 в 08:00

6 ответов

Это отличный ответ от @ sergiy-kolodyazhnyy со следующими изменениями:

Не проверять имя part в имени (некоторые из моих дисков не используют разделы). Используйте by-id вместо by-path, поэтому можно использовать менее двусмысленный p.startswith("usb-"). Выключение питания в отдельном контуре (несколько устройств могут быть подключены к одной и той же мощности). Проверьте, что устройство существует до выключения (опять же, связанный источник питания). Запуск команд (run_cmd) возвращает логическое значение, основанное на успехе. Уведомлять конечный результат (количество устройств, монтируемых / отключенных). Используйте Python3 (выход подпроцесса в байтах).

Update: сделал этот более общий инструмент: udisksctl_usb_all [--mount, --unmount, --unmount-power-off]. Его можно использовать для всех трех операций.

#!/usr/bin/env python3 import os import subprocess import sys def run_cmd(cmdlist): ''' utility: reusable function for running external commands ''' try: stdout = subprocess.check_output(cmdlist, stderr=subprocess.STDOUT) return True except subprocess.CalledProcessError as cpe: print(cpe.output) # GtkDialog error should be ignored. if not b'GtkDialog mapped without a transient parent' in cpe.output: return error_dialog(cpe.output, ' '.join(cmdlist)) return False def error_dialog(err_msg, called_cmd): ''' Displays graphical error dialog and exits the script''' print(called_cmd) subprocess.call(['zenity', '--error', '--text', err_msg, '--title', called_cmd]) sys.exit(1) def find_usb_partitions(): ''' Constructs a list of USB partitions ''' return tuple( os.path.realpath(os.path.join('/dev/disk/by-id', p)) for p in os.listdir('/dev/disk/by-id') if p.startswith('usb-') ) def find_mounted_devs(): devs = [] with open('/proc/mounts') as mounts: for line in mounts: if line.startswith('/dev/'): devs.append(line.split(' ', 1)[0]) return devs def unmount_all(power_off=False): unmount_len = 0 parts = find_usb_partitions() devs = find_mounted_devs() mounted_parts = tuple(i for i in parts if i in devs) for part in mounted_parts: if run_cmd(['udisksctl', 'unmount', '-b', part]): unmount_len += 1 if power_off: # Some drives may be linked regarding power, check each exists first. for part in mounted_parts: if os.path.exists(part): run_cmd(['udisksctl', 'power-off', '-b', part]) if unmount_len: run_cmd(['notify-send', 'Unmounted {} file-systems!'.format(unmount_len)]) else: run_cmd(['notify-send', 'Nothing to unmount!']) def mount_all(): mount_len = 0 parts = find_usb_partitions() devs = find_mounted_devs() # only include non-numbered devices if numbered ones don't exist # don't try to mout /dev/sdc if /dev/sdc1 exists. parts_numbered = set() for p in parts: p_strip = p.rstrip('0123456789') if p != p_strip: parts_numbered.add(p_strip) parts = tuple(p for p in parts if p not in parts_numbered) del parts_numbered unmounted_parts = tuple(i for i in parts if i not in devs) for part in unmounted_parts: if run_cmd(['udisksctl', 'mount', '-b', part]): mount_len += 1 if mount_len: run_cmd(['notify-send', 'Mounted {} file-systems!'.format(mount_len)]) else: run_cmd(['notify-send', 'Nothing to mount!']) if __name__ == '__main__': if "--mount" in sys.argv: mount_all() elif "--unmount" in sys.argv: unmount_all(power_off=False) elif "--unmount-power-off" in sys.argv: unmount_all(power_off=True) else: print("Expected one of ['--mount', '--unmount' or '--unmount-power-off'] to be passed.")
1
ответ дан 18 July 2018 в 09:56

Один из вариантов заключается в использовании команды umount с: sudo umount / media / user / your-usb-drive

Для определения правильного диска вы можете использовать команду mount: mount | grep usb

0
ответ дан 18 July 2018 в 09:56

Вот скрипт python, который соберет все смонтированные разделы USB и выполнит udisksctl unmount -b <DEV> для каждого из них. Стандартные правила для этого рабочего ярлыка применяются: убедитесь, что сценарий является исполняемым, и укажите полный путь к сценарию как команду.

Как запрошено, только ошибки будут отображаться в диалоговом окне GUI, другой вывод не будет показан.

#!/usr/bin/env python import os import subprocess import sys def run_cmd(cmdlist): """ utility: reusable function for running external commands """ try: stdout = subprocess.check_output(cmdlist,stderr=subprocess.STDOUT) except subprocess.CalledProcessError as cpe: # GtkDialog error should be ignored. if not "GtkDialog mapped without a transient parent" in cpe.output: return error_dialog(cpe.output," ".join(cmdlist)) def error_dialog(err_msg,called_cmd): """ Displays graphical error dialog and exits the script""" subprocess.call(['zenity','--error','--text',err_msg,'--title',called_cmd]) sys.exit(1) def find_usb_partitions(): """ Constructs a list of USB partitions """ return tuple( os.path.realpath(os.path.join("/dev/disk/by-path",p)) for p in os.listdir("/dev/disk/by-path") if 'usb' in p and 'part' in p ) def find_mounted_devs(): devs=[] with open('/proc/mounts') as mounts: for line in mounts: dev = line.split()[0] if dev.startswith('/dev/'): devs.append(dev) return devs def main(): parts=find_usb_partitions() devs=find_mounted_devs() mounted_parts=tuple(i for i in parts if i in devs) for part in mounted_parts: run_cmd(['udisksctl', 'unmount', '-b',part]) run_cmd(['udisksctl', 'power-off', '-b',part]) if __name__ == '__main__': main()

Дополнительные мысли

Пока скрипт работает, Я считаю, что идея размонтировать из ярлыка немного избыточна. Такая задача требует по крайней мере некоторого участия пользователя. Если цель состоит в том, чтобы размонтировать без терминала, уже есть способы сделать это. Например, если вы являетесь пользователем Unity, у вас уже есть значок устройства на панели запуска, из которого вы можете щелкнуть правой кнопкой мыши и извлечь устройство. Я написал Udisks-Indicator, который вы можете использовать для размонтирования разделов с графического индикатора (и который использует некоторые из тех же идей, которые я использовал в этом ответе). В любом случае есть альтернативы, но я лично предостерег бы от использования ярлыков для отключения вещей. Но опять же, это только мое личное мнение.

2
ответ дан 18 July 2018 в 09:56

Это отличный ответ от @ sergiy-kolodyazhnyy со следующими изменениями:

Не проверять имя part в имени (некоторые из моих дисков не используют разделы). Используйте by-id вместо by-path, поэтому можно использовать менее двусмысленный p.startswith("usb-"). Выключение питания в отдельном контуре (несколько устройств могут быть подключены к одной и той же мощности). Проверьте, что устройство существует до выключения (опять же, связанный источник питания). Запуск команд (run_cmd) возвращает логическое значение, основанное на успехе. Уведомлять конечный результат (количество устройств, монтируемых / отключенных). Используйте Python3 (выход подпроцесса в байтах).

Update: сделал этот более общий инструмент: udisksctl_usb_all [--mount, --unmount, --unmount-power-off]. Его можно использовать для всех трех операций.

#!/usr/bin/env python3 import os import subprocess import sys def run_cmd(cmdlist): ''' utility: reusable function for running external commands ''' try: stdout = subprocess.check_output(cmdlist, stderr=subprocess.STDOUT) return True except subprocess.CalledProcessError as cpe: print(cpe.output) # GtkDialog error should be ignored. if not b'GtkDialog mapped without a transient parent' in cpe.output: return error_dialog(cpe.output, ' '.join(cmdlist)) return False def error_dialog(err_msg, called_cmd): ''' Displays graphical error dialog and exits the script''' print(called_cmd) subprocess.call(['zenity', '--error', '--text', err_msg, '--title', called_cmd]) sys.exit(1) def find_usb_partitions(): ''' Constructs a list of USB partitions ''' return tuple( os.path.realpath(os.path.join('/dev/disk/by-id', p)) for p in os.listdir('/dev/disk/by-id') if p.startswith('usb-') ) def find_mounted_devs(): devs = [] with open('/proc/mounts') as mounts: for line in mounts: if line.startswith('/dev/'): devs.append(line.split(' ', 1)[0]) return devs def unmount_all(power_off=False): unmount_len = 0 parts = find_usb_partitions() devs = find_mounted_devs() mounted_parts = tuple(i for i in parts if i in devs) for part in mounted_parts: if run_cmd(['udisksctl', 'unmount', '-b', part]): unmount_len += 1 if power_off: # Some drives may be linked regarding power, check each exists first. for part in mounted_parts: if os.path.exists(part): run_cmd(['udisksctl', 'power-off', '-b', part]) if unmount_len: run_cmd(['notify-send', 'Unmounted {} file-systems!'.format(unmount_len)]) else: run_cmd(['notify-send', 'Nothing to unmount!']) def mount_all(): mount_len = 0 parts = find_usb_partitions() devs = find_mounted_devs() # only include non-numbered devices if numbered ones don't exist # don't try to mout /dev/sdc if /dev/sdc1 exists. parts_numbered = set() for p in parts: p_strip = p.rstrip('0123456789') if p != p_strip: parts_numbered.add(p_strip) parts = tuple(p for p in parts if p not in parts_numbered) del parts_numbered unmounted_parts = tuple(i for i in parts if i not in devs) for part in unmounted_parts: if run_cmd(['udisksctl', 'mount', '-b', part]): mount_len += 1 if mount_len: run_cmd(['notify-send', 'Mounted {} file-systems!'.format(mount_len)]) else: run_cmd(['notify-send', 'Nothing to mount!']) if __name__ == '__main__': if "--mount" in sys.argv: mount_all() elif "--unmount" in sys.argv: unmount_all(power_off=False) elif "--unmount-power-off" in sys.argv: unmount_all(power_off=True) else: print("Expected one of ['--mount', '--unmount' or '--unmount-power-off'] to be passed.")
1
ответ дан 24 July 2018 в 19:28

Один из вариантов заключается в использовании команды umount с: sudo umount / media / user / your-usb-drive

Для определения правильного диска вы можете использовать команду mount: mount | grep usb

0
ответ дан 24 July 2018 в 19:28
  • 1
    Проблема с этим - вызов sudo из привязки ключа, не является практичным, также я не думаю, что уведомления будут обрабатываться с пользой. – ideasman42 21 July 2017 в 09:44
  • 2
    Линии с usb в них не гарантированно появятся на выходе mount | grep 'usb', только в редких случаях, когда это имеет название устройства USB или точки монтирования. Кроме того, что сказал ideman42 - вызов sudo из ярлыка не работает, потому что вы 1) либо должны жестко закодировать свой пароль в скрипте, который небезопасен, либо 2) запрашивать пароль пользователя каждый раз, что со временем становится раздражает большинство пользователей (не для меня лично, а для большинства пользователей). sudo запрашивает только в stdin, поэтому вам также нужно как-то поднять всплывающее окно GUI с запросом пароля, что является другой задачей – Sergiy Kolodyazhnyy 21 July 2017 в 11:02

Вот скрипт python, который соберет все смонтированные разделы USB и выполнит udisksctl unmount -b <DEV> для каждого из них. Стандартные правила для этого рабочего ярлыка применяются: убедитесь, что сценарий является исполняемым, и укажите полный путь к сценарию как команду.

Как запрошено, только ошибки будут отображаться в диалоговом окне GUI, другой вывод не будет показан.

#!/usr/bin/env python import os import subprocess import sys def run_cmd(cmdlist): """ utility: reusable function for running external commands """ try: stdout = subprocess.check_output(cmdlist,stderr=subprocess.STDOUT) except subprocess.CalledProcessError as cpe: # GtkDialog error should be ignored. if not "GtkDialog mapped without a transient parent" in cpe.output: return error_dialog(cpe.output," ".join(cmdlist)) def error_dialog(err_msg,called_cmd): """ Displays graphical error dialog and exits the script""" subprocess.call(['zenity','--error','--text',err_msg,'--title',called_cmd]) sys.exit(1) def find_usb_partitions(): """ Constructs a list of USB partitions """ return tuple( os.path.realpath(os.path.join("/dev/disk/by-path",p)) for p in os.listdir("/dev/disk/by-path") if 'usb' in p and 'part' in p ) def find_mounted_devs(): devs=[] with open('/proc/mounts') as mounts: for line in mounts: dev = line.split()[0] if dev.startswith('/dev/'): devs.append(dev) return devs def main(): parts=find_usb_partitions() devs=find_mounted_devs() mounted_parts=tuple(i for i in parts if i in devs) for part in mounted_parts: run_cmd(['udisksctl', 'unmount', '-b',part]) run_cmd(['udisksctl', 'power-off', '-b',part]) if __name__ == '__main__': main()

Дополнительные мысли

Пока скрипт работает, Я считаю, что идея размонтировать из ярлыка немного избыточна. Такая задача требует по крайней мере некоторого участия пользователя. Если цель состоит в том, чтобы размонтировать без терминала, уже есть способы сделать это. Например, если вы являетесь пользователем Unity, у вас уже есть значок устройства на панели запуска, из которого вы можете щелкнуть правой кнопкой мыши и извлечь устройство. Я написал Udisks-Indicator, который вы можете использовать для размонтирования разделов с графического индикатора (и который использует некоторые из тех же идей, которые я использовал в этом ответе). В любом случае есть альтернативы, но я лично предостерег бы от использования ярлыков для отключения вещей. Но опять же, это только мое личное мнение.

2
ответ дан 24 July 2018 в 19:28
  • 1
    Благодаря! Мне нужно было изменить его, чтобы работать на меня, хотя, включенный в собственный ответ, не стесняйтесь использовать, и я удалю его. – ideasman42 21 July 2017 в 11:53
  • 2
    @ ideasman42 oh, я никоим образом не против того, чтобы люди меняли свой код, поэтому не стесняйтесь хранить его как автономный ответ. Что касается сценария bash, который вы изначально использовали, я бы сказал, что это так, чтобы другие пользователи могли извлечь из этого выгоду. Я не читал его слишком внимательно, но казалось, что у него есть потенциал. – Sergiy Kolodyazhnyy 21 July 2017 в 12:28

Другие вопросы по тегам:

Похожие вопросы: