Skip to content

Commit 9eebe2b

Browse files
committed
Changed option names & updated readme
- Removed config file - Renamed command line args - Added option to save, but not host output files
1 parent c3a29ef commit 9eebe2b

File tree

5 files changed

+48
-36
lines changed

5 files changed

+48
-36
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ sftp-config.json
2929
.make
3030
Makefile
3131
.vscode
32+
/**/dv_????????????????????????????????
3233

3334
# PyInstaller
3435
# Usually these files are written by a python script from a template

README.md

+24-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,24 @@
1-
# dv
2-
Disk Usage Visualization
1+
# dv - Disk Usage Visualization
2+
<br><br>
3+
![Scan of /Applications on OSX](preview.png)
4+
<br><br><br>
5+
6+
About
7+
----------
8+
9+
dv is a command line tool for visualizing disk data usage on systems that don't have access to a graphical environment. After scanning a directory, dv generates an interactive webpage that displays useful information about the disk's contents. This webpage is a sunburst partition layout, where each subdirectory is displayed as a portion of the scanned directory.
10+
11+
Hovering over a directory shows its size and percentage of the whole. dv is multiprocessed, and can be used to quickly visualize what is taking up space on a system.
12+
13+
Check out a [pre-generated plot](https://engineering.arm.gov/~dohnalek/dv_99c6f258f11a8f14a4d460f8e1c9fc4d/index.html?id=local).
14+
15+
Usage
16+
-----------
17+
dv has several options that can be explored with
18+
```bash
19+
dv --help
20+
```
21+
To get started as quickly as possible with a basic directory scan and plot, clone this repository, cd to the `python` directory, and run:
22+
```bash
23+
python3 dv.py <directory-to-scan> --save-and-host <directory-to-store-plot>
24+
```

preview.png

346 KB
Loading

python/config.json

-3
This file was deleted.

python/dv.py

+23-31
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
from multiprocessing import Manager, Process
1515

1616

17+
DV_LOCATION = os.path.dirname(os.path.realpath(__file__))
18+
WWW_LOCATION = os.path.join(os.path.dirname(DV_LOCATION), "www")
19+
20+
1721
class Server(SimpleHTTPRequestHandler):
1822
def end_headers(self):
1923
self.gzip_headers()
@@ -37,11 +41,17 @@ def parseArgs():
3741
parser.add_argument("-u", "--unique", action="store_true", help="If passed, the 'unique' flag generates a new plot with a unique URL instead of overwriting the previous scan")
3842
parser.add_argument("-m", "--modtime", action="store_true", help="If passed, the 'modtime' flag adds the most recent modification time of any file in each directory to the generated plot")
3943
parser.add_argument("-f", "--fade", action="store_true", help="If passed, the 'fade' flag will make directories in the generated plot appear more opaque if their files haven't been touched for a long time")
40-
parser.add_argument("-o", "--output", help="A directory containing the generated plot and web page will be placed on disk at the specified location, after the scan finishes, a local HTTP server will start and serve the plot")
44+
parser.add_argument("-s", "--save", help="A directory containing the generated plot and web page will be placed on disk at the specified location, after the scan finishes")
45+
parser.add_argument("-sh", "--save-and-host", help="The same as -s, but after scanning, dv will start a server to serve the newly generated plot")
4146

4247
args = parser.parse_args()
4348
args.root = args.directory
4449

50+
if args.save_and_host:
51+
args.save = args.save_and_host
52+
if args.save:
53+
args.save = os.path.realpath(args.save)
54+
4555
if args.root == "/":
4656
args.root = "/./"
4757
if args.root.endswith("/"):
@@ -55,27 +65,6 @@ def parseArgs():
5565
return args
5666

5767

58-
def parseConfig():
59-
"""Parse the file config.json found in the same directory
60-
"""
61-
if not args.output:
62-
return {}
63-
64-
config_name = os.path.join(os.path.dirname(os.path.realpath(__file__)), "config.json")
65-
66-
try:
67-
config_contents = open(config_name).read()
68-
except Exception:
69-
sys.exit("Couldn't find config file")
70-
71-
try:
72-
config_json = json.loads(config_contents)
73-
except Exception:
74-
sys.exit("Malformed JSON in config file")
75-
76-
return config_json
77-
78-
7968
def getRandomToken():
8069
"""getRandomToken generates a cryptographically secure 25 character token, where each character
8170
has 62 possible values, providing a total of 62^25 possible output values
@@ -198,7 +187,7 @@ def joinNode(node):
198187

199188

200189
def writeFile(run_id, data, file_root="/data/tmp/dv"):
201-
if args.output:
190+
if args.save:
202191
file_name = "scan.json"
203192
else:
204193
file_name = "dv_{}.json".format(run_id)
@@ -211,22 +200,21 @@ def writeFile(run_id, data, file_root="/data/tmp/dv"):
211200

212201

213202
def writeOutDir(run_id, data):
214-
dir_path = os.path.join(args.output, "dv_" + run_id)
203+
dir_path = os.path.join(args.save, "dv_" + run_id)
215204

216205
if os.path.exists(dir_path):
217206
shutil.rmtree(dir_path)
218207

219-
shutil.copytree(config["web_dir"], dir_path)
208+
shutil.copytree(WWW_LOCATION, dir_path)
220209

221210
writeFile(run_id, data, dir_path)
222211

223212

224213
if __name__ == "__main__":
225214
args = parseArgs()
226-
config = parseConfig()
227215

228-
if args.output and not os.path.exists(config["web_dir"]):
229-
sys.exit("Web dir '{}' not found".format(config.web_dir))
216+
if args.save and not os.path.exists(WWW_LOCATION):
217+
sys.exit("Web dir '{}' not found".format(WWW_LOCATION))
230218

231219
if args.unique:
232220
getToken = getRandomToken
@@ -244,6 +232,7 @@ def writeOutDir(run_id, data):
244232
for proc in range(args.processes):
245233
new_proc = Process(target=scanDir, args=(work_queue, done_queue, ))
246234
processes.append(new_proc)
235+
new_proc.daemon = True
247236
new_proc.start()
248237

249238
collection_vars = {"tree_depth": 0, "oldest_dir": time.time(), "newest_dir": 0}
@@ -287,17 +276,20 @@ def writeOutDir(run_id, data):
287276
file_json = json.dumps(scaffold)
288277
token = getToken()
289278

290-
if args.output:
279+
if args.save:
291280
writeOutDir(token, file_json)
292281
else:
293282
writeFile(token, file_json)
294283

295284
print("Your plot can be found at:")
296-
if args.output:
297-
dir_path = os.path.join(args.output, "dv_" + token)
285+
if args.save_and_host:
286+
dir_path = os.path.join(args.save, "dv_" + token)
298287
print("localhost:8000?id=local")
299288
os.chdir(dir_path)
300289
server = HTTPServer(("localhost", 8000), Server)
301290
server.serve_forever()
291+
elif args.save:
292+
dir_path = os.path.join(args.save, "dv_" + token)
293+
print(dir_path)
302294
else:
303295
print("https://engineering.arm.gov/dv?id=%s" % token)

0 commit comments

Comments
 (0)