-
Notifications
You must be signed in to change notification settings - Fork 10
/
remove.py
executable file
·53 lines (46 loc) · 1.49 KB
/
remove.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/usr/bin/env python3
# 2018, Georg Sauthoff <[email protected]>
# SPDX-License-Identifier: GPL-3.0-or-later
import argparse
import os
import time
import subprocess
import sys
# cf. https://unix.stackexchange.com/q/444611/1131
def remove(dev):
filename = '/sys/block/{}/device/../../../../remove'.format(dev)
with open(filename, 'wb', buffering=0) as f:
f.write(b'1\n')
# probably also tirggered by the remove, just being paranoid here
# the flushbufs generally makes sense when there were some raw writes
# to the device
def flush(dev):
subprocess.check_output(['blockdev', '--flushbufs', dev])
def detach(filename):
devname = os.path.realpath(filename)
dev = os.path.basename(devname)
flush(devname)
# in case the remove isn't properly implemented/paranoia
time.sleep(13)
remove(dev)
try:
os.stat(devname)
raise RuntimeError(
'Device {} still present after removal'.format(devname))
except FileNotFoundError:
pass
time.sleep(3)
def main():
p = argparse.ArgumentParser(
description='Sync USB drive cache, power-off and remove device ')
p.add_argument('filenames', metavar='DEVICE_PATH', nargs='+',
help='path to USB disk device (e.g. /dev/sdb)')
args = p.parse_args()
try:
for filename in args.filenames:
detach(filename)
except Exception as e:
print('error: {}'.format(e), file=sys.stderr)
return 1
if __name__ == '__main__':
sys.exit(main())