Ένας φίλος στο φόρουμ ζήτησε να υπολογίσει το συνολικό χώρο που χρησιμοποιεί σε όλους τους δίσκους, ώστε να υπολογίσει πόση χωρητικότητα θα χρειαστεί για ένα backup. Η απάντηση σε ένα μοντέρνο σύστημα δεν είναι τόσο απλή, οπότε παρουσιάζω εδώ μια πρώτη προσπάθεια υπολογισμού που θα καλύψει το 99% των περιπτώσεων οικιακής χρήσης.
Ο απλός τρόπος
Η ίδια η εντολή μπορεί να το υπολογίσει
df -h --total
λύθηκε το πρόβλημα; Όχι. Κατ αρχήν θα πρέπει να προσθέσουμε την παράμετρο -l
για να βγάλουμε έξω δικτυακούς δίσκους, αν αυτό έχει νόημα στην περίπτωση μας. Επίσης θα πρέπει να αφαιρέσουμε τους μη δίσκους, οπότε
df -h -l -x tmpfs -x devtmpfs --total
και θα΄πάρουμε αυτό που θέλουμε. Τελειώσαμε; Στις περισσότερες περιπτώσεις ναι, αλλά θέλει προσοχή στο τι θεωρεί το df σαν δίσκο και τι όχι. Και αυτό δεν είναι κάτι τόσο απλό (docker, zfs, btrfs), και θέλουμε περισσότερο έλεγχο.
Ένας ποιο πολύπλοκος τρόπος
Θα δείξω ένα πρόχειρο τρόπο να το κάνεις αυτό με την βοήθεια του awk (δυστυχώς δεν υπήρξε κάποιο ενδιαφέρον και δεν συνέχισα τα tutorials). Σε ένα τερματικό θα δώσει τα παρακάτω
df | awk '/dev\/sd/ {sum += $3} END {print sum}' | numfmt --to=si
Η τελευταία εντολή numfmt
κάνει μετατροπές μονάδων και είναι για να μετατρέψει τα bytes σε μια μονάδα που να καταλαβαίνουμε. Χρησιμοποίησα τις μονάδες του SI, όπου 1GΒ=1000MB
. Αν θέλεις μετρήσεις σε Megibytes, όπου 1GΒ=1024MB
, θα γράψεις --to=iec
.
Αν θέλεις το άθροισμα του ελεύθερου χώρου, κάτι που οι αναγνώστες θα βρουν ποιο χρήσιμο
df | awk '/dev\/sd/ {sum += $4} END {print sum}' | numfmt --to=iec
Τα παραπάνω θα υπολογίσουν το άθροισμα των συνδεμένων (mounted) δίσκων. Δυστυχώς δεν μπορώ να κάνω τίποτα για τους δίσκους που έχεις μέσα στο συρτάρι σου
Ένα μικρό πρόβλημα
Στον υπολογιστή μου έχω το btrfs
σαν σύστημα αρχείων. Η εικόνα του που υπάρχει στο άρθρο δείχνει ένα filesystem πολλές φορές. Ένα mount point μπορεί να γίνει ‘bind’ σε άλλο σημείο, το docker και το ZFS επίσης μπορεί να δείχνουν να σύστημα αρχείων πολλές φορές.
Για να μην εμφανιστεί λοιπόν πολλές φορές ένα σύστημα αρχείων στο άθροισμα θα πρέπει να το λάβουμε υπόψη μόνο μια φορά. Υπάρχουν αρκετοί τρόποι για να γίνει αυτό, αλλά θα παραμείνω στον awk
και θα κάνω χρήση “associative arrays” για να κρατήσω μόνο ένα νούμερο. Στο τέλος θα τα αθροίσω. Και ιδού το αποτέλεσμα
df | awk '/dev\/sd/ {sums[$1]=$3} END {for (i in sums) tot += sums[i]; print tot}' | numfmt --to=iec
Αφήνω σαν άσκηση την πλήρη λύση, αν και σε αυτό το σημείο, ήρθε η ώρα να αφήσουμε πίσω μας την λύση σε μια γραμμή και να φτιάξουμε κάποια εντολή σε ένα εκτελέσιμο αρχείο.
Προσθήκη στο τέλος της df
Έτσι για την αλητεία, να δείξω και πως μπορείς να προσθέσεις κάτι στο τέλος της df
. Ρεαλιστικά βέβαια θα το έκανες ένα script που θα καλούσε την df
δυο φορές, ή που θα την καλούσε μια φορά και θα έβαζε το αποτέλεσμα κάπου. Αλλά σαν άσκηση ας δούμε πως μπορούμε να διακλαδώσουμε μια ροή και πώς καλούμε το κέφυφος μέσα απο την `awk’.
Η εντολή τότε είναι
df -l
| tee >(cat)
| awk '
/dev\/sd/ { sum += $3 }
END { printf "Total sum of used space: ";
system ("echo " sum "| numfmt --to=iec") }
'
Τα παραπάνω θα μπουν σε μια γραμμή
df -l | tee >(cat) | awk '/dev\/sd/ {sum += $3} END { printf "Total sum: "; system ("echo " sum "| numfmt --to=iec")}'
Αφήνω σαν άσκηση την τελική λύση, αλλά σε αυτο το σημείο ήρθε η ώρα να αφήσουμε την λύση της μιας γραμμής και να φτιάξουμε κάποιο εκτελέσιμο script σε ένα αρχείο. Όποιος θέλει ας δώσει μια τέτοια λύση.
Καταλήγοντας
Μια γενική λύση είναι πολύ ποιο πολύπλοκη και σε κάποιες περιπτώσεις είναι και μια μάταιη φιλοσοφική αναζήτηση. Ποια είναι η χρησιμοποιούμενη χωρητικότητα ενός συστήματος αρχείων σε fsή σε
btrfs`; Αλλά το παραπάνω θα καλύψει το 99% των περιπτώσεων. Αν δεν καλύπτει την περίπτωση σου, και δεν βρίσκεις τι αλλαγές θέλει, εδώ είμαστε και ρώτησε ή μοιράσου την λύση σου.