Για τα αρχεία ρυθμίσεων του Bash

To Bash όταν ξεκινάει διαβάζει κάποια αρχεία ρυθμίσεων. Συχνά νέοι (αλλά και παλιοί) χρήστες δυσκολεύονται να καταλάβουν τι ακριβώς συμβαίνει, και υπάρχει μια σκοτεινή τέχνη γύρω από το τι ακριβώς συμβαίνει. Σκοτεινή; Όχι, ακριβώς. Ας φωτίσουμε τις σκοτεινές γωνιές.

Ας ξεκαθαρίσουμε πρώτα κάποια πράγματα.

1. Login shell

Όταν ξεκινάει το Bash μέσα από ένα τερματικό ή μια σύνδεση ssh συνήθως έχεις ένα login shell. Όταν μέσα από κάποιο κέλυφος ξεκινάς το Bash δεν παίρνεις login shell. Το ίδιο συνήθως και όταν ξεκινάς κάποιο εξομοιωτή τερματικού (δηλαδή το πρόγραμμα με το όνομα τερματικό), έκτος αν ρυθμιστεί διαφορετικά.

2. Interactive Shell

Όταν λέμε Bash είτε εννοούμε κάποιο πρόγραμμα με το οποίο αλληλεπιδράμε, δίδουμε εντολές και βλέπουμε το αποτέλεσμα, είτε μια γλώσσα προγραμματισμού που γράφουμε μικρά προγράμματα. Όταν το πρόγραμμα τερματίζει, τότε τερματίζει και το Bash που το τρέχει. Στην πρώτη περίπτωση έχουμε ένα Interactive Shell.


Οπότε έχουμε τις παρακάτω περιπτώσεις:

  • Interactive Login shell:
    Σύνδεση έκτος γραφικής συνεδρίας ή με ssh ή με εξωτερικό τερματικό.
    Εκτέλεση με bash --login, sudo /bin/login, exec -l /bin/bash, su -
  • Interactive Non-login shell:
    Σύνδεση με γραφικό πρόγραμμα τερματικού,
    κέλυφος μέσα σε κέλυφος
  • Non-interactive Non-login shell:
    Όταν τρέχουμε κάποιο script
  • Non-interactive Login shell:
    Όταν τρέχουμε κάποιο script μέσω ssh (σπάνια περίπτωση)
    echo command | ssh ...

Γιατί τα λέμε όλα αυτά; Γιατί κάθε περίπτωση χρησιμοποιεί διαφορετικά αρχεία.

Η διαδικασία εκκίνησης του Bash

Ας δούμε σε κάθε περίπτωση τι αρχεία ρυθμίσεων θα συμβουλευτεί:

Το παραπάνω διάγραμμα (δανεισμένο από εδώ) δείχνει τα αρχεία που θα συμβουλευτεί κάθε φορά.

Interactive Login shell

Ας δούμε αναλυτικά τι συμβαίνει στον υπολογιστή μου σε αυτή την περίπτωση.

  • Πρώτα θα συμβουλευτεί το αρχείο (αν υπάρχει) /etc/profile.
  • Στη συνέχεια το πρώτο (και μόνο το πρώτο) από τα αρχεία
    • ~/.bash_profile
    • ~/.bash_login
    • ~/.profile

Και εδώ είναι η πρώτη παγίδα. Στήνεις κάποιο πρόγραμμα βάζει κάποια πράγματα στο ~/.bash_login. Έχεις όμως ένα ~/.bash_profile και δε βλέπει τις ρυθμίσεις. Τα βάζει στο ~/.bash_profile; Τότε χάνεις τις ρυθμίσεις στο ~/.bash_login. H συμβουλή μου; Μην έχεις κανένα από αυτά :slight_smile:. Έκτος από το ~/.profile. Αλλά αυτό τεχνικά ανήκει σε ένα απλούστερο κέλυφος το sh.

Τελειώσαμε; Πολύ βιαστικό σε βλέπω. Ας δούμε λίγο τα αρχεία αυτά στη διανομή μου. Στη δική σου τα πράγματα ίσως να είναι διαφορετικά.

Το αρχείο /etc/profile θα καλέσει πρώτα το αρχείο /etc/bash.bashrc και στη συνέχεια όλα τα αρχεία στον κατάλογο /etc/profile.d/. Το πρώτο αρχείο περιέχει χρήσιμα πράγματα για interactive shells. Για παράδειγμα, θα φορτώσει τους κανόνες για τη συμπλήρωση εντολών με το πλήκτρο TAB.

Τα αρχεία στον κατάλογο /etc/profile.d/ (δείτε τα) περιέχουν κανόνες για συγκεκριμένα προγράμματα. Εδώ είναι το καταλληλότερο μέρος αν θέλουμε να αλλάξουμε κάτι καθολικά για όλους τους χρήστες.

Μένει το αρχείο ~/.profile. Αυτό συνήθως το μόνο που κάνει είναι να καλέσει το αρχείο ~/.bashrc (αν υπάρχει).

Ιnteractive Non-login shell

Εδώ τα πράγματα είναι πιο απλά. Θα συμβουλευτεί μόνο δυο αρχεία, τα

  • /etc/bash.bashrc
  • ~/.bashrc

Οπότε το αρχείο που θα κάνουμε τις αλλαγές ανά χρήστη είναι το αρχείο ~/.bashrc. Αν κρατήσεις κάτι από αυτό το κείμενο κράτα μόνο αυτό.

Αλλά μισό λεπτό, πως είναι δυνατόν να έχει όλες τις ρυθμίσεις από τα αρχεία ενός interactive shell; Ότι έχει οριστεί στην προηγούμενη περίπτωση υπάρχει ήδη! Πως συμβαίνει αυτό; Η απάντηση είναι στο δέντρο των διεργασιών και στο τι κληρονομεί μια διεργασία από τον μπαμπά της. Και το γραφικό περιβάλλον θα το ξεκινήσει κάποιο interactive shell.

Non-interactive Non-login shell

Εδώ δε θα φορτωθεί τίποτα έκτος αν έχει οριστεί μια μεταβλητή περιβάλλοντος $BASH_ENV. Τότε θα εκτελεστεί το όνομα αρχείου που περιέχει. Προσοχή στην κληρονομικότητα σε αυτή την περίπτωση!

Προβλήματα και λύσεις

1. Cronjobs:
Αχ πόσο σύνηθες. Ένα script τρέχει μια χαρά στη γραμμή εντολών, αλλά αποτυγχάνει σαν cronjob. Γιατί; Γιατί θα τρέξει σαν non-intrective. Δε θα κληρονομήσει τίποτα, δε θα φορτώσει τα αρχεία. Τα alias και το $PATH θα είναι διαφορετικά. Η λύση είναι να βάζουμε πλήρη διαδρομές στις εντολές. Κάτι που γενικά είναι καλή ιδέα και best practice.

2. Τι είδους κέλυφος χρησιμοποιώ;

  • Για να δεις αν έχεις login shell
    shopt login_shell
  • Για να δεiς αν έχεις interactive shell
    είναι ορισμένη η μεταβλητή $PS1. Σε κώδικά [ "${PS1-}" ]
    ή με την βοήθεια της μεταβλητής $-. Σε κώδικά [[ $- == *i* ]]

Γιατί τόση πολυπλοκότητα;

Γιατί υπάρχει μεγάλη ιστορία στο UNIX και θέλουμε προς τα πίσω συμβατότητα. Και μιας και μιλάμε για πολυπλοκότητα, ιδού με λίγο παραπάνω λεπτομέρεια:

Την εικόνα τη βρήκα εδώ. Μπορούμε να μην τρέξουμε κάποια αρχεία με --noprofile και/ή --norc.

Και επειδή έχουμε τα αρχεία από τη μια κατάσταση να τραβάνε αρχεία από την άλλη μια άλλη εικόνα είναι (απο εδώ και εδώ):

Σίγουρα μπορούν να λεχθούν και άλλα όπως για το pam ή το ssh ή ακόμα και το zsh, αλλά θα σταματήσω εδώ. Ελπίζω να φανεί χρήσιμο, και διορθώστε με ελεύθερα σε τυχόν λάθη.

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