- 리눅스 터미널을 켤 때마다 C드라이브의 사용량이 자동으로 보이는 대시보드를 만들 것이다
~ $ source ~/.bashrc
===== DISK DASHBOARD =====
C Drive Usage (2026-03-08)
[##################################------] 85%
Used: 404.6GB / 476.8GB
발단
- 필자는 주로
WSL2에서 터미널을 다루고 있는데, 가끔C:\,D:\드라이브에 남은 용량이 없어서 디스크를 정리해야 할 때가 있다. - 그럴 때면 주로 작업하는 디렉터리 및 window의 사용자 디렉터리나
%AppData%의 cache 디렉터리로 이동하여du -sh *로 각 디렉터리 중 불필요하게 큰 용량을 차지하는 부분을 자세히 조사하여 필요 없는 파일을 삭제하곤 한다 - 삭제 목표는 주로
df의 출력에서C:\의Available과Use%를 높이는 것으로 설정한다 - 그러던 어느날
df로 당시의 가용용량을 파악하는 것을 넘어 매일df의 출력을 저장해 두면 그 추이를 나중에 확인할 때 편할 것이라는 생각이 들었다
전개
df 출력 전처리
- 자 그럼 시작해보자.
awk를 사용할수 있으므로 먼저df의 출력을awk로 가공하자- 먼저
df의 manual page(man df)를 보면df의 각 필드에 대한 설명이 나온다--output[=FIELD_LIST] use the output format defined by FIELD_LIST, or print all fields if FIELD_LIST is omitted. FIELD_LIST is a comma-separated list of columns to be included. Valid field names are: 'source', 'fstype', 'itotal', 'iused', 'iavail', 'ipcent', 'size', 'used', 'avail', 'pcent', 'file' and 'target' (see info page). df의 기본 출력이 어떤field를 보여주는지--output을 통해 검증하자
~ $ df
Filesystem 1K-blocks Used Available Use% Mounted on
drivers 499952636 424267596 75685040 85% /usr/lib/wsl/drivers
/dev/sdd 1055762868 134215988 867843408 14% /
C:\ 499952636 424267596 75685040 85% /mnt/c
snapfuse 128 128 0 100% /snap/bare/5
snapfuse 340224 340224 0 100% /snap/code/219
snapfuse 65408 65408 0 100% /snap/core20/2686
snapfuse 75776 75776 0 100% /snap/core22/2216
tmpfs 800380 8 800372 1% /run/user/1000
...
~ $ df --output=source,size,used,avail,pcent,target
Filesystem 1K-blocks Used Avail Use% Mounted on
drivers 499952636 424269376 75683260 85% /usr/lib/wsl/drivers
/dev/sdd 1055762868 134216048 867843348 14% /
C:\ 499952636 424269376 75683260 85% /mnt/c
snapfuse 128 128 0 100% /snap/bare/5
snapfuse 340224 340224 0 100% /snap/code/219
snapfuse 65408 65408 0 100% /snap/core20/2686
snapfuse 75776 75776 0 100% /snap/core22/2216
tmpfs 800380 8 800372 1% /run/user/1000
...
df의 기본 출력은source,size,used,avail,pcent,target필드라는 것을 알 수 있다.df의 output은 형식을 가진 문자열(formatted string)이므로,csv형태로 가공하는awk스크립트를 만들자
function join(arr, sep) {
acc = arr[1]
for (i = 2; i <= length(arr); i++) {
acc = acc sep arr[i]
}
return acc
}
NR == 1 {
cmd = "date -I"
cmd | getline date
close(cmd)
print "date,source,size,used,avail,pcent,target"
next
}
{
split($0, arr)
str = join(arr, ",")
printf "%s,%s\n",date,str
}
YYYY-MM-DD형식을 만드는 가장 편한 방법은date -I를 이용하는 것이다awk안에서 bash command를 파이프와getline그리고 출력을 받는 변수로 연결하면 output을 변수에 저장할수 있다- 이 방법을 사용할 때는 반드시 command를 닫도록 주의하자
- 각 필드를 “,”로 join하는 방법은
printf "%s,%s,...",$1,$2,...도 있지만 $0을 한번 더split하여arr로 만든 후join하는 방법도 있다. 여기서는 후자를 채택하였다
~ $ df | awk -f $HOME/.cli/awk/df_to_csv.awk
date,source,size,used,avail,pcent,target
2026-03-08,drivers,499952636,424269604,75683032,85%,/usr/lib/wsl/drivers
2026-03-08,/dev/sdd,1055762868,134216088,867843308,14%,/
2026-03-08,C:\,499952636,424269604,75683032,85%,/mnt/c
2026-03-08,snapfuse,128,128,0,100%,/snap/bare/5
2026-03-08,snapfuse,340224,340224,0,100%,/snap/code/219
2026-03-08,snapfuse,65408,65408,0,100%,/snap/core20/2686
2026-03-08,snapfuse,75776,75776,0,100%,/snap/core22/2216
2026-03-08,tmpfs,800380,8,800372,1%,/run/user/1000
...
DB 저장
- 이제 이 출력을 어딘가에 저장해야 한다
- 하루에 최대 한번만 snapshot을 저장하고 레코드가 누적되는 구조이기 때문에 database가 성격에 맞다
- 그렇다고 외부에서 접속하는 기능은 필요 없으므로
postgresql씩은 필요 없을 것 같다 - 어디까지나 local machine에 대한 상태를 DB로 관리하기 위함이니 local에서 파일로 관리되는
sqlite3나duckdb가 성격에 맞을 것 같다 - 사용하는 명령어의 성격이 bash native에 가까우니
duckdb까지 의존성을 추가할 필요는 없을것 같으니sqlite3를 채택한다
- db path는
~/machine.db로 정했다. 목적을 잘 반영하는 것 같다.- 전략은 sqlite의
.mode csv.import /path/to/target.csv target_table를 이용해csv내용을 table에 넣는 것이다
- 전략은 sqlite의
- 위에서 만든
df | awk -f $HOME/.cli/awk/df_to_csv.awk의 출력을 이용해 만든csv를sql로 변환하자
$ df | awk -f $HOME/.cli/awk/df_to_csv.awk > ~/df.csv
- csv의 header만 읽어 table을 create하는 sql로 전환하는 awk는 만들어두면 사용할 일이 많을 것 같다
$ awk -f $HOME/.cli/awk/csv2createsql.awk ~/df.csv
$ cat $HOME/.cli/awk/csv2createsql.awk
function join(arr, sep) {
acc = arr[1]
for (i = 2; i <= length(arr); i++) {
acc = acc sep arr[i]
}
return acc
}
function strip(str) {
gsub(/^\s+|\s+$/, "", str)
return str
}
### if not using gawk but awk
# NR == 1 {
# print "create table " table_name "("
# str = join(arr, " text,\n")
# split($0, arr, ",")
# str = join(arr, " text,\n")
# print strip(str) " text"
# print ");"
# }
### FINENAME, FNR are supported only if using gawk
FNR == 1 {
filename = path_arr[split(FILENAME,path_arr,"/")]
table_name = substr(filename, 1, index(filename, ".") - 1)
split($0, arr, ",")
print "create table " table_name "("
str = join(arr, " text,\n")
print strip(str) " text"
print ");"
}
~ $ awk -f $HOME/.cli/awk/csv2createsql.awk df.csv
create table df(
date text,
source text,
size text,
used text,
avail text,
pcent text,
target text
);
- 위의 awk script는
gawk에서만 제공되는FILENAME변수를 사용한 것에 주의하자.- 그냥
awk로는awk -v table_name=df-f csv2createsql.awk df.csv같은 형식으로 사용하면 된다
- 그냥
- 이제 메인 shell file을 만들자
recorddf
#!/bin/bash
df_to_csv_file="$HOME/.cli/awk/df_to_csv.awk"
today=$(date -I)
tmpfile=$(mktemp)
sqlite3 ~/machine.db -cmd "
create table if not exists df(
date text,
source text,
size text,
used text,
avail text,
pcent text,
target text
);
" ".quit"
sqlite3 ~/machine.db -cmd "delete from df where date = '$today'" ".quit"
df | awk -f "$df_to_csv_file" > "$tmpfile"
sqlite3 ~/machine.db \
-cmd ".mode csv" \
-cmd ".import --skip 1 $tmpfile df" \
".quit"
sqlite3 ~/machine.db -cmd "select count(1) from df where date = '$today'" ".quit"
sqlite3의-cmd옵션은sqlite3로 진입한 interactive 환경에서 실행하는 것과 같다- 실제로 위의 shell 파일을 만들 때 interactive 환경에서 여러번 시도하며 작성했다.
- 이제 위 shell file을 실행가능한 위치에 넣고
PATH에 추가한다export PATH=$PATH:$HOME/.cli/bincp recorddf $HOME/.cli/bin
대시보드 생성 및 자동 실행
- 한동안 위의 설정으로 상태를 저장만 해 오다가 어느날 위의 스크립트를 자동으로 실행하고 주된 관심사인
C:\,D:\드라이브의 사용량을 bar plot으로 보면 좋겠다는 생각이 들었다 - 먼저 나의
sqlite3schema와 저장된 형태를 gpt에게 주고 bar plot을 생성하는 스크립트를 만들어 달라고 했더니 다음과 같은 스크립트가 나왔다
#!/bin/bash
DB="$HOME/machine.db"
TODAY=$(date -I)
ROW=$(sqlite3 "$DB" "
SELECT size, used, pcent
FROM df
WHERE date = '$TODAY'
AND source = 'C:\\'
LIMIT 1;
")
if [ -n "$ROW" ]; then
TOTAL=$(echo "$ROW" | cut -d'|' -f1)
USED=$(echo "$ROW" | cut -d'|' -f2)
PERCENT=$(echo "$ROW" | cut -d'|' -f3 | tr -d '%')
BAR_WIDTH=40
FILLED=$((PERCENT * BAR_WIDTH / 100))
EMPTY=$((BAR_WIDTH - FILLED))
BAR=$(printf "%0.s#" $(seq 1 $FILLED))
SPACE=$(printf "%0.s-" $(seq 1 $EMPTY))
echo ""
echo "===== DISK DASHBOARD ====="
echo "C Drive Usage ($TODAY)"
printf "[%s%s] %s%%\n" "$BAR" "$SPACE" "$PERCENT"
printf "Used: %.1fGB / %.1fGB\n" \
"$(echo "$USED / 1024 / 1024" | bc -l)" \
"$(echo "$TOTAL / 1024 / 1024" | bc -l)"
echo ""
fi
- 정상동작을 확인했으므로, 자동으로 실행하도록 설정만 하면 된다
~/.bashrc에 추가하면 된다$ echo "recorddf 1>/dev/null" >> ~/.bashrc$ echo "bash ~/.cli/bin/diskdashboard" >> ~/.bashrc
- 이제 리눅스 터미널을 켤 때마다 C드라이브의 사용량이 자동으로 보인다