Υπολογισμός συνολικού χώρου στον δίσκο

Ένας φίλος στο φόρουμ ζήτησε να υπολογίσει το συνολικό χώρο που χρησιμοποιεί σε όλους τους δίσκους, ώστε να υπολογίσει πόση χωρητικότητα θα χρειαστεί για ένα 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) δίσκων. Δυστυχώς δεν μπορώ να κάνω τίποτα για τους δίσκους που έχεις μέσα στο συρτάρι σου :grinning:

Ένα μικρό πρόβλημα

Στον υπολογιστή μου έχω το btrfs σαν σύστημα αρχείων. Η εικόνα του που υπάρχει στο άρθρο δείχνει ένα filesystem πολλές φορές. Ένα mount point μπορεί να γίνει ‘bind’ σε άλλο σημείο, το docker και το ZFS επίσης μπορεί να δείχνουν να σύστημα αρχείων πολλές φορές.

Για να μην εμφανιστεί λοιπόν πολλές φορές ένα σύστημα αρχείων στο άθροισμα θα πρέπει να το λάβουμε υπόψη μόνο μια φορά. Υπάρχουν αρκετοί τρόποι για να γίνει αυτό, αλλά θα παραμείνω στον awk και θα κάνω χρήση “associative arrays” για να κρατήσω μόνο ένα νούμερο. Στο τέλος θα τα αθροίσω. Και ιδού το αποτέλεσμα :exploding_head:

 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’.

Η εντολή τότε είναι :dizzy_face: :face_with_head_bandage: :exploding_head:

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% των περιπτώσεων. Αν δεν καλύπτει την περίπτωση σου, και δεν βρίσκεις τι αλλαγές θέλει, εδώ είμαστε και ρώτησε ή μοιράσου την λύση σου.

4 «Μου αρέσει»

Ευχαριστώ πολύ για τον κόπο σου!

Νομίζω ότι η απλούστερη λύση όλων, με την προϋπόθεση ότι έχουμε κάνει mount όλους τους δίσκους μας είναι:

inxi -D

Και ένα παράδειγμα με output από το δικό μου σύστημα:

george@george-Ryzen:~$ inxi -D
Drives:
  Local Storage: total: 4.68 TiB used: 1.89 TiB (40.5%) 
  ID-1: /dev/sda vendor: Samsung model: SSD 860 EVO 500GB size: 465.76 GiB 
  ID-2: /dev/sdb vendor: Toshiba model: HDWD130 size: 2.73 TiB 
  ID-3: /dev/sdc vendor: Seagate model: ST31000528AS size: 931.51 GiB 
  ID-4: /dev/sdd vendor: Western Digital model: WD6401AALS-00L3B2 
  size: 596.17 GiB 

Σημειώνω ότι μας δείχνει σωστά πάντα το συνολικό local space, είτε έχουμε κάνει mount τους δίσκους είτε όχι.

Όμως για να δείξει σωστά το συνολικό used space πρέπει να έχουν γίνει mount όλοι οι δίσκοι, αλλιώς διαβάζει σαν used space μόνο ότι μπορεί να δει στους mounted δίσκους.

5 «Μου αρέσει»