Wie wird ein Shell-Skript automatisch erzeugt?

3

Wie kann man ein Shell-Skript veranlassen, seine Befehle als Quellbefehle auszuführen, ohne den Ausdruck "source scriptname.sh" zum Starten des Skripts verwenden zu müssen? Grundsätzlich möchte ich ./scriptname.sh eingeben und die Befehle so verwenden, als ob source zum Ausführen des Shell-Skripts verwendet wurde.

Andrew-George Hondrari
quelle
Möchten Sie nur die Befehle im Skript ausführen?
Terdon
nein, ich möchte, dass sie als Source-Shell-Befehle fungieren, ohne das Schlüsselwort source im Ausführungsaufruf zu verwenden
Andrew-George Hondrari
2
Könnten Sie Ihr Skript (oder die relevanten Teile davon) posten, damit wir besser verstehen können, was Sie versuchen, bitte? Erklären Sie auch, warum Sie source nicht verwenden möchten.
Terdon
2
Wenn es nur die Menge der Eingabe Sie wollen , zu vermeiden, beachten Sie, dass die Syntax . fileäquivalent ist source fileeigentlich sourceein „bashism“ (Bash spezifisch) und der Punkt - Operator ist „Standard“ (POSIX).
Daniel Andersson
@Daniel Der sourceBefehl stammt ursprünglich aus Bill Joys csh .
Nicole Hamilton

Antworten:

4

In keiner der Unix-Shells können Sie ein Skript als eines markieren, das immer so beschaffen sein sollte, wie Sie es sich erhofft haben. Ich würde ein aliasoder eine Prozedur erstellen , um das zu tun, was Sie wollen, und es in mein Startskript einfügen. Zum Beispiel in tcsh:

alias scriptname source \!\!

In bash könnte man es als Prozedur schreiben:

scriptname( ) { source scriptname.sh $*; }
Nicole Hamilton
quelle
Verwenden Sie "$@"stattdessen $*- Ersteres ist die einzig sichere Methode, um Parameter zu übergeben, die möglicherweise Leerzeichen enthalten.
Glenn Jackman
0

Sie können eine Funktion verwenden bash, mit der Sie Benutzereingaben abfangen und darauf reagieren können, wobei jede übliche Befehlsausführung außer Kraft gesetzt wird.

Fügen Sie Ihrem bashStartskript Folgendes hinzu :

shopt -s extdebug
function auto_source_names {
    local CMD=$BASH_COMMAND
    if [[ -f "$CMD" ]] && [[ ! -x "$CMD" ]] ; then
        source "$CMD"
        return 1
    else
        return 0
    fi
}
trap 'auto_source_names' DEBUG

Dadurch wird die Funktion für jeden ausgeführten Befehl aufgerufen. Wenn es sich um den Namen einer Datei handelt, die nicht ausführbar ist (ansonsten würden wir auch legitime ./foo.shAufrufe blockieren ), wird sie als Quelle verwendet und kein Befehl ausgeführt. Achten Sie auf Dateien mit dem Namen lsoder rmim selben Verzeichnis. Sie können zusätzliche Sicherheitsvorkehrungen treffen, z. B. die .shDateierweiterung oder den fileHinweis, dass der Name eine Textdatei ist.


Beispiel:

Erstellen foo.sh:

FOO=bar

Dann:

$ echo $FOO
$ foo.sh
$ echo $FOO
bar
Daniel Beck
quelle
Ich gebe zu, es ist eine clevere Lösung, aber ist es wirklich ratsam, die Standardsprache zu ändern, indem Skripte in einem separaten Prozess isoliert und stattdessen beschafft werden? Scheint, als würde das eine Menge Sachen kaputt machen. Ich würde die Notwendigkeit, ein Skript zu erstellen, eher als Ausnahme als als Regel behandeln, aber die Eingabe vereinfachen, wenn ich auf eines stoße.
Nicole Hamilton
@Daniel: Dies schlägt fehl, wenn der Benutzer versucht, die Befehlsdatei (Skript) mit Argumenten wie in foo.sh barrelaufzurufen, da BASH_COMMAND (und folglich CMD) auf den gesamten einfachen Befehl gesetzt wird und daher der –fTest fehlschlägt. Ich schlage vor, dass Sie hinzufügen eval set –– "$CMD"und den –fTest auf tun $1; dann source "$@".
Scott
@Daniel: Ihre Aussage: "Achten Sie auf Dateien mit dem Namen lsoder rmim selben Verzeichnis." Könnte erweitert werden: " Beachten Sie, dass nicht ausführbare Dateien im aktuellen Verzeichnis die normale Befehlsverarbeitungslogik der Shell vollständig beeinträchtigen." ich sage das , weil auch (nicht ausführbare Dateien) wie alias, export, history, jobs, etc ..., wird bezogen werden, zu ignorieren und überschreiben ihre Definition als builtin Befehle.
Scott
@Nicole: Ich stimme Ihnen in zwei von drei Punkten zu: (1) Es ist eine clevere Lösung, und (2) Ich glaube, es ist nicht ratsam. Aber (3) (es sei denn, ich habe etwas übersehen oder falsch interpretiert) @ Daniels Lösung ändert nicht das Standardverhalten der Shell, indem Skripte in einem separaten Prozess isoliert und stattdessen beschafft werden. Beachten Sie, dass bei [[ ! –x "$CMD" ]]Faktor –– Skripten, für die der ausführbare Modus festgelegt ist, der auto_source_namesRückkehrcode 0 (Null) nicht mehr ausreicht, wodurch die Shell angewiesen wird, sie normal zu verarbeiten.
Scott
@ Nicole: FYI, meine Sorge ist, dass diese Technik zu inklusiv ist. (Ich unterstütze von ganzem Herzen @ Daniels Vorschlag, eine .shErweiterung zu fordern .) Ich hätte Angst, etwas zu schreiben, wie conv.cwenn ich cc conv.coder meinte vi conv.c, und die Shell sourcemeine C-Quelldatei zu haben. (Ich würde nicht wirklich erwarten, dass irgendetwas in einer C-Quelldatei ein gültiger Unix-Befehl ist, aber ich würde auch nicht den harten Weg herausfinden wollen.)
Scott
-3

Die erste Zeile muss den Pfad zum Interpreter enthalten:
#! /bin/bash

Dann machen Sie die Skriptdatei ausführbar:
chmod +x scriptname.sh

Jetzt können Sie ausführen ./scriptname.sh, um es auszuführen.

Andrew Crabb
quelle
1
Dies ist die grundlegende Ausführung, ich fragte etwas anderes
Andrew-George Hondrari
@AndreiGeorgeHondrari, es scheint, dass die meisten nicht mit Ihren 'Source Shell-Befehlen' vertraut sind (ich habe jahrelange Erfahrung mit Linux und noch nie davon gehört). vielleicht könntest du erklären, was du ein bisschen besser willst.
Frank Thomas
@Frank Thomas, bash.cyberciti.biz/guide/Source_command . Sehen Sie, was Nicole Hamilton geantwortet hat. Das ist die Lösung.
Andrew-George Hondrari
Danke, das war sehr informativ. Aus dem Artikel, den Sie verlinkt haben, können Sie eine 'source'-Anweisung in das Treiberskript direkt unter dem shebang einfügen und dann das Treiberskript mit der Angabe' source 'aufrufen. Haben Sie ein Treiberskript oder versuchen Sie nur, eine Funktion in einer Quellenskriptdatei direkt über die CLI aufzurufen?
Frank Thomas
@Frank Wenn Sie ein Skript wie gewohnt als Befehl ausführen, gibt die Shell eine Kopie von sich als neuen Prozess aus, um das Skript auszuführen. Das isoliert alles, was dieses Skript tut, von der Kopie der Shell, die Sie interaktiv verwenden. Wenn das Skript die Umgebungsvariablen oder das aktuelle Verzeichnis ändert, geht alles verloren, wenn das Skript beendet wird. Der Status der Kopie der Shell, mit der Sie interagieren, wird nicht geändert. Die sourceAnweisung bewirkt, dass das Skript ausgeführt wird, ohne dass diese Isolation erzeugt wird. Alle Befehle im Skript werden von Ihrer Kopie der Shell ausgeführt und können ihren Status ändern.
Nicole Hamilton