Κυριακή, 29 Σεπτεμβρίου, 2024
ΑρχικήSales EventsΒελτιστοποιώντας την εκτέλεση εντολών Bash με τη μέθοδο εκτέλεσης μια φορά τη...

Βελτιστοποιώντας την εκτέλεση εντολών Bash με τη μέθοδο εκτέλεσης μια φορά τη φορά


Βασικά Takeaways

  • Βεβαιωθείτε ότι μόνο μία παρουσία του σεναρίου σας εκτελείται χρησιμοποιώντας pgrep, lsof ή flock για να αποτρέψετε προβλήματα ταυτόχρονης χρήσης.
  • Εφαρμόστε εύκολα ελέγχους για να τερματίσετε αυτόματα ένα σενάριο εάν εντοπιστούν άλλες εμφανίσεις που εκτελούνται.
  • Αξιοποιώντας τις εντολές exec και env, η εντολή flock μπορεί να επιτύχει όλα αυτά με μία γραμμή κώδικα.



Ορισμένα σενάρια Linux έχουν τέτοια επιβάρυνση εκτέλεσης, η εκτέλεση πολλών παρουσιών ταυτόχρονα πρέπει να αποτραπεί. Ευτυχώς, υπάρχουν διάφοροι τρόποι για να το πετύχετε αυτό στα δικά σας σενάρια Bash.


Μερικές φορές μια είναι αρκετή

Ορισμένα σενάρια δεν θα πρέπει να εκκινηθούν εάν μια προηγούμενη παρουσία αυτού του σεναρίου εξακολουθεί να εκτελείται. Εάν το σενάριό σας καταναλώνει υπερβολικό χρόνο CPU και RAM ή δημιουργεί μεγάλο εύρος ζώνης δικτύου ή thrashing δίσκου, ο περιορισμός της εκτέλεσής του σε μία παρουσία τη φορά είναι κοινή λογική.

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

Μια τεχνική για να αποφύγετε αυτά τα σενάρια προβλημάτων είναι να ελέγξετε το σενάριο ότι δεν εκτελούνται άλλες εκδόσεις του. Εάν εντοπίσει άλλα αντίγραφα που εκτελούνται, το σενάριο τερματίζεται αυτόματα.


Μια άλλη τεχνική είναι η μηχανική του σεναρίου με τέτοιο τρόπο ώστε να κλειδώνει όταν εκκινείται, αποτρέποντας την εκτέλεση άλλων αντιγράφων.

Θα εξετάσουμε δύο παραδείγματα της πρώτης τεχνικής και στη συνέχεια θα εξετάσουμε έναν τρόπο για να κάνουμε τη δεύτερη.

Χρήση του pgrep για την αποτροπή της ταυτόχρονης λειτουργίας

Η εντολή pgrep πραγματοποιεί αναζήτηση στις διεργασίες που εκτελούνται σε έναν υπολογιστή Linux και επιστρέφει το αναγνωριστικό διεργασίας των διεργασιών που ταιριάζουν με το μοτίβο αναζήτησης.

Έχω ένα σενάριο που ονομάζεται loop.sh. Περιέχει έναν βρόχο for που εκτυπώνει την επανάληψη του βρόχου και μετά αδράνει για ένα δευτερόλεπτο. Αυτό το κάνει δέκα φορές.

#!/bin/bash

for (( i=1; i=10; i+=1 ))
do
 echo "Loop:" $i
 sleep 1
done

exit 0

Ρύθμισα δύο περιπτώσεις να εκτελείται και μετά χρησιμοποίησα το pgrep για να το αναζητήσω με το όνομά του.

pgrep loop.sh 


Εντοπίζει τις δύο περιπτώσεις και αναφέρει τα αναγνωριστικά διεργασίας τους. Μπορούμε να προσθέσουμε την επιλογή -c (count) έτσι ώστε το pgrep να επιστρέφει τον αριθμό των παρουσιών.

pregp -c loop.sh 
Χρησιμοποιώντας την εντολή pgrep για να μετρήσετε τις εκτελούμενες εμφανίσεις του σεναρίου loop.sh.

Μπορούμε να χρησιμοποιήσουμε αυτόν τον αριθμό παρουσιών στο σενάριό μας. Εάν η τιμή που επιστρέφεται από το pgrep είναι μεγαλύτερη από μία, πρέπει να εκτελούνται περισσότερες από μία παρουσίες και το σενάριό μας θα κλείσει.

Θα δημιουργήσουμε ένα σενάριο που χρησιμοποιεί αυτήν την τεχνική. Θα το ονομάσουμε pgrep-solo.sh.

Η σύγκριση if ελέγχει εάν ο αριθμός που επιστρέφεται από το pgrep είναι μεγαλύτερος από ένα. Εάν είναι, το σενάριο κλείνει.


if [ $(pgrep -c pgrep-solo.sh) -gt 1 ]; then
 echo "Another instance of $0 is running. Stopping."
 exit 1
fi

Εάν ο αριθμός που επιστρέφεται από το pgrep είναι ένας, το σενάριο μπορεί να συνεχίσει. Εδώ είναι το πλήρες σενάριο.

#!/bin/bash

echo "Starting."


if [ $(pgrep -c pgrep-solo.sh) -gt 1 ]; then
 echo "Another instance of $0 is running. Stopping."
 exit 1
fi


for (( i=1; i=10; i+=1 ))
do
 echo "Loop:" $i
 sleep 1
done

exit 0

Αντιγράψτε το στον αγαπημένο σας επεξεργαστή και αποθηκεύστε το ως pgrep-solo.sh. Στη συνέχεια, κάντε το εκτελέσιμο με το chmod.


chmod +x pgrep-loop.sh 
Χρησιμοποιώντας το chmod για να κάνετε το σενάριο pgrep-solo.sh εκτελέσιμο.

Όταν τρέχει, μοιάζει με αυτό.

./pgrep-solo.sh 
Εκτέλεση του σεναρίου pgrep-solo.sh.

Αλλά αν προσπαθήσω να το ξεκινήσω με ένα άλλο αντίγραφο που εκτελείται ήδη σε άλλο παράθυρο τερματικού, το εντοπίζει και βγαίνει.

./pgrep-solo.sh 
Εκτέλεση του σεναρίου pgrep-solo.sh όταν εκτελείται ήδη μια άλλη παρουσία.

Χρήση του lsof για την αποτροπή της ταυτόχρονης λειτουργίας

Μπορούμε να κάνουμε κάτι παρόμοιο με την εντολή lsof.


Αν προσθέσουμε την επιλογή -t (terse), το lsof παραθέτει τα αναγνωριστικά διεργασίας.

lsof -t loop.sh 
Χρησιμοποιώντας την εντολή lsof για να παραθέσουμε τα αναγνωριστικά διεργασίας των εκτελούμενων παρουσιών του σεναρίου loop.sh.

Μπορούμε να διοχετεύσουμε την έξοδο από το lsof στο wc. Η επιλογή -l (γραμμές) μετράει τον αριθμό των γραμμών που, σε αυτό το σενάριο, είναι ίδιος με τον αριθμό των αναγνωριστικών διεργασίας.

lsof -t loop.sh | wc -l 
Χρησιμοποιώντας την εντολή lsof για να μετρήσετε τις εκτελούμενες εμφανίσεις του σεναρίου loop.sh.

Μπορούμε να το χρησιμοποιήσουμε ως βάση του τεστ στη σύγκριση if στο σενάριό μας.

Αποθηκεύστε αυτήν την έκδοση ως lsof-solo.sh.

#!/bin/bash

echo "Starting."


if [ $(lsof -t "$0" | wc -l) -gt 1 ]; then
 echo "Another instance of $0 is running. Stopping."
 exit 1
fi


for (( i=1; i=10; i+=1 ))
do
 echo "Loop:" $i
 sleep 1
done

exit 0

Χρησιμοποιήστε το chmod για να το κάνετε εκτελέσιμο.


chmod +x lsof-solo.sh 
Χρησιμοποιώντας το chmod για να κάνετε ένα εκτελέσιμο σενάριο.

Τώρα, με το σενάριο lsof-solo.sh να εκτελείται σε άλλο παράθυρο τερματικού, δεν μπορούμε να ξεκινήσουμε ένα δεύτερο αντίγραφο.

./lsof-solo.sh 
Το σενάριο lsof-solo.sh αυτοτερματίζεται επειδή εκτελείται ήδη μια άλλη παρουσία.

Η μέθοδος pgrep απαιτεί μόνο μία κλήση σε ένα εξωτερικό πρόγραμμα (pgrep), η μέθοδος lsof απαιτεί δύο (lsof και wc). Αλλά το πλεονέκτημα που έχει η μέθοδος lsof έναντι της μεθόδου pgrep είναι ότι μπορείτε να χρησιμοποιήσετε τη μεταβλητή $0 στη σύγκριση if. Αυτό κρατά το όνομα του σεναρίου.


Σημαίνει ότι μπορείτε να μετονομάσετε το σενάριο και θα εξακολουθεί να λειτουργεί. Δεν χρειάζεται να θυμάστε να επεξεργαστείτε τη γραμμή σύγκρισης if και να εισαγάγετε το νέο όνομα του σεναρίου. Η μεταβλητή $0 περιλαμβάνει το ‘./’ στην αρχή του ονόματος του σεναρίου (όπως ./lsof-solo.sh), και το pgrep δεν του αρέσει.

Χρήση του κοπαδιού για την πρόληψη της ταυτόχρονης λειτουργίας

Η τρίτη τεχνική μας χρησιμοποιεί την εντολή flock, η οποία έχει σχεδιαστεί για να ορίζει κλειδώματα αρχείων και καταλόγων μέσα από σενάρια. Ενώ είναι κλειδωμένο, καμία άλλη διεργασία δεν μπορεί να έχει πρόσβαση στον κλειδωμένο πόρο.

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

[ "${GEEKLOCK}" != "$0" ] && exec env GEEKLOCK="$0" flock -en "$0" "$0" "$@" || : 

Θα αποκωδικοποιήσουμε αυτά τα ιερογλυφικά σύντομα. Προς το παρόν, ας ελέγξουμε απλώς ότι λειτουργεί. Αποθηκεύστε αυτό ως flock-solo.sh.

#!/bin/bash

[ "${GEEKLOCK}" != "$0" ] && exec env GEEKLOCK="$0" flock -en "$0" "$0" "$@" || :

echo "Starting."


for (( i=1; i=10; i+=1 ))
do
 echo "Loop:" $i
 sleep 1
done

exit 0

Φυσικά, πρέπει να το κάνουμε εκτελέσιμο.

chmod +x flock-solo.sh 
Χρησιμοποιώντας το chmod για να κάνετε το σενάριο flock-solo.sh εκτελέσιμο.

Ξεκίνησα το σενάριο σε ένα παράθυρο τερματικού και μετά προσπάθησα να το εκτελέσω ξανά σε άλλο παράθυρο τερματικού.


./flock-solo
./flock-solo
./flock-solo
Τρεις ανεπιτυχείς και μία επιτυχημένη κυκλοφορία του σεναρίου flock-solo.sh.

Δεν μπορώ να ξεκινήσω το σενάριο μέχρι να ολοκληρωθεί η παρουσία στο άλλο παράθυρο τερματικού.

Ας ξεδιαλέξουμε τη γραμμή που κάνει τα μαγικά. Στην του είναι η εντολή του κοπαδιού.

flock -en "$0" "$0" "$@" 

Η εντολή flock χρησιμοποιείται για το κλείδωμα ενός αρχείου ή καταλόγου και, στη συνέχεια, για την εκτέλεση μιας εντολής. Οι επιλογές που χρησιμοποιούμε είναι -e (αποκλειστική) και -n (nonblocking).

Η αποκλειστική επιλογή σημαίνει ότι εάν καταφέρουμε να κλειδώσουμε το αρχείο, κανείς άλλος δεν μπορεί να έχει πρόσβαση σε αυτό. Η επιλογή nonblocking σημαίνει ότι εάν δεν καταφέρουμε να αποκτήσουμε κλειδαριά, σταματάμε αμέσως την προσπάθεια. Δεν ξαναπροσπαθούμε για κάποιο χρονικό διάστημα, υποκλινόμαστε ευθύς με χάρη.

Το πρώτο $0 υποδεικνύει το αρχείο που θέλουμε να κλειδώσουμε. Αυτή η μεταβλητή περιέχει το όνομα του τρέχοντος σεναρίου.


Το δεύτερο $0 είναι η εντολή που θέλουμε να εκτελέσουμε εάν καταφέρουμε να αποκτήσουμε ένα κλείδωμα. Και πάλι, περνάμε στο όνομα αυτού του σεναρίου. Γιατί η κλειδαριά κλειδώνει όλους χώρια από εμάς, μπορούμε να εκκινήσουμε το αρχείο σεναρίου.

Μπορούμε να περάσουμε παραμέτρους στην εντολή που εκκινείται. Χρησιμοποιούμε το $@ για να μεταβιβάσουμε τυχόν παραμέτρους της γραμμής εντολών που μεταβιβάστηκαν σε αυτό το σενάριο, στη νέα επίκληση του σεναρίου που πρόκειται να ξεκινήσει από το flock.

Έτσι, έχουμε αυτό το σενάριο που κλειδώνει το αρχείο του σεναρίου και στη συνέχεια ξεκινά μια άλλη παρουσία του. Αυτό είναι σχεδόν αυτό που θέλουμε, αλλά υπάρχει ένα πρόβλημα. Όταν ολοκληρωθεί η δεύτερη παρουσία, το πρώτο σενάριο θα συνεχίσει την επεξεργασία του. Ωστόσο, έχουμε ένα άλλο κόλπο στο μανίκι μας για να το καλύψουμε, όπως θα δείτε.


Χρησιμοποιούμε μια μεταβλητή περιβάλλοντος που ονομάζουμε GEEKLOCK για να υποδείξουμε εάν ένα σενάριο που εκτελείται πρέπει να εφαρμόσει το κλείδωμα ή όχι. Εάν το σενάριο έχει ξεκινήσει και δεν υπάρχει κλείδωμα, πρέπει να εφαρμοστεί το κλείδωμα. Εάν το σενάριο έχει ξεκινήσει και υπάρχει ένα κλείδωμα στη θέση του, δεν χρειάζεται να κάνει , μπορεί απλώς να τρέξει. Με ένα σενάριο σε λειτουργία και το κλείδωμα στη θέση του, δεν μπορούν να εκκινηθούν άλλες περιπτώσεις του σεναρίου.

[ "${GEEKLOCK}" != "$0" ]  

Αυτό το τεστ μεταφράζεται ως “return true εάν η μεταβλητή περιβάλλοντος GEEKLOCK είναι δεν

env GEEKLOCK="$0" 

Η εντολή env χρησιμοποιείται για την εκτέλεση άλλων εντολών σε τροποποιημένα περιβάλλοντα. Τροποποιούμε το περιβάλλον μας δημιουργώντας τη μεταβλητή περιβάλλοντος GEEKLOCK και ορίζοντας την στο όνομα του σεναρίου. Η εντολή που πρόκειται να εκκινήσει το env είναι η εντολή flock και η εντολή flock εκκινεί τη δεύτερη παρουσία του σεναρίου.


Η δεύτερη παρουσία του σεναρίου εκτελεί τον έλεγχο για να δει αν η μεταβλητή περιβάλλοντος GEEKLOCK δεν κάνει υπάρχει, αλλά διαπιστώνει ότι υπάρχει. Το || εκτελείται το τμήμα της εντολής, το οποίο δεν περιέχει τίποτα παρά μόνο μια άνω και κάτω τελεία ‘:’ που είναι στην πραγματικότητα μια εντολή που δεν κάνει τίποτα. Στη συνέχεια, η διαδρομή εκτέλεσης διατρέχει το υπόλοιπο σενάριο.

Αλλά έχουμε ακόμα το ζήτημα του πρώτου σεναρίου να συνεχίζει τη δική του επεξεργασία όταν το δεύτερο σενάριο έχει τερματιστεί. Η λύση σε αυτό είναι η εντολή exec. Αυτό εκτελεί άλλες εντολές αντικαθιστώντας τη διαδικασία κλήσης με τη διαδικασία που ξεκίνησε πρόσφατα.

exec env GEEKLOCK="$0" flock -en "$0" "$0" "$@"  

Οπότε η πλήρης σειρά είναι:


  • Το exec εκκινεί το env και αντικαθιστά την αρχική διαδικασία σεναρίου με τη νέα διαδικασία env.
  • Η διαδικασία env δημιουργεί τη μεταβλητή περιβάλλοντος και εκκινεί το flock.
  • Το flock κλειδώνει το αρχείο σεναρίου και εκκινεί μια νέα παρουσία του σεναρίου που εντοπίζει τη μεταβλητή περιβάλλοντος, εκτελεί το || ρήτρα και το σενάριο μπορεί να φτάσει στο τέλος του.
  • Επειδή το αρχικό σενάριο αντικαταστάθηκε από τη διαδικασία env, δεν υπάρχει πλέον και δεν μπορεί να συνεχίσει την εκτέλεσή του όταν τερματιστεί το δεύτερο σενάριο.
  • Επειδή το αρχείο σεναρίου είναι κλειδωμένο όταν εκτελείται, δεν είναι δυνατή η εκκίνηση άλλων παρουσιών έως ότου το σενάριο που εκκινήθηκε από το flock σταματήσει να εκτελείται και απελευθερώσει το κλείδωμα.

Αυτό μπορεί να ακούγεται σαν την πλοκή του Εναρξηαλλά λειτουργεί υπέροχα. Αυτή η μία γραμμή είναι σίγουρα μια γροθιά.

Για λόγους σαφήνειας, είναι το κλείδωμα του αρχείου σεναρίου που εμποδίζει την εκκίνηση άλλων παρουσιών και όχι ο εντοπισμός της μεταβλητής περιβάλλοντος. Η μεταβλητή περιβάλλοντος λέει μόνο α τρέξιμο δέσμη ενεργειών είτε για να ρυθμίσετε την κλειδαριά είτε ότι η κλειδαριά είναι ήδη στη θέση της.


Κλείδωμα και φόρτωση

Είναι ευκολότερο από ό,τι θα περίμενε κανείς να διασφαλίσει ότι εκτελείται μόνο μία μόνο παρουσία ενός σεναρίου ταυτόχρονα. Και οι τρεις αυτές τεχνικές λειτουργούν. Αν και είναι το πιο περίπλοκο στη λειτουργία, το flock one-liner είναι το πιο εύκολο να μπει σε οποιοδήποτε σενάριο.



VIA: HowToGeek.com

Dimitris Marizas
Dimitris Marizashttps://www.cybervista.gr
Αφοσιωμένος λάτρης κινητών Samsung, ο Δημήτρης έχει εξελίξει μια ιδιαίτερη σχέση με τα προϊόντα της εταιρίας, εκτιμώντας τον σχεδιασμό, την απόδοση και την καινοτομία που προσφέρουν. Γράφοντας και διαβάζοντας τεχνολογικά νέα από όλο τον κόσμο.
RELATED ARTICLES

ΑΦΗΣΤΕ ΜΙΑ ΑΠΑΝΤΗΣΗ

εισάγετε το σχόλιό σας!
παρακαλώ εισάγετε το όνομά σας εδώ

- Advertisment -

Most Popular

Recent Comments