[LINUX] Skriptsprache C - Wie wird eine Textdatei ohne Shebang ausgeführt?

Ist es möglich, eine C-Sprachquelldatei zu erstellen, die so ausgeführt werden kann, wie sie ist?

Es gibt viele Definitionen für eine Skriptsprache, aber die Bequemlichkeit, die Quelldatei "ausführen" zu können, ist wichtig. Angenommen, Sie haben eine Quelldatei in C-Sprache wie die folgende.

$ file hello.c 
hello.c: C source, ASCII text
$ gcc -Wall ./hello.c 
$ ./a.out
Hello, script language C.

Richtiger Code für die C-Sprache, der ohne Vorwarnung ordnungsgemäß kompiliert wird. Angenommen, diese Quelldatei wird mit dem angegebenen Ausführungsattribut ausgeführt

$ #Machen Sie die Quelldatei zu einer ausführbaren Datei wie einer Skriptsprache
$ chmod +x hello.c
$ ./hello.c
Hello, script language C.

Wenn es ohne Probleme wie ausgeführt wird, kann C-Sprache als Skriptsprache bezeichnet werden. Überlegen Sie, ob Sie eine solche Datei erstellen können.

Vorschlag 1: Verwenden Sie TCC mit Shebang

In der Skriptsprache gibt die erste Zeile einer Quelldatei den Befehl zum Ausführen dieser Quelldatei an, z. B. "#! / Bin / sh", "#! / Usr / bin / python". Es ist "shebang. Verwenden wir dies auch in C-Sprache.

Der TCC-Compiler verfügt über eine Option namens "-run", die automatisch kompiliert und ausgeführt wird. Sie können diese jedoch auch in der Shebang-Zeile angeben.

hello_tcc.c


#!/usr/bin/tcc -run
#include <stdio.h>
int main (int argc, char* argv[]) {
	printf("Hello, script language C.\n");
	return 0;
}

Jetzt können Sie den Befehl tcc direkt in Ihrer Umgebung ausführen.

$ chmod +x hello_tcc.c
$ ./hello_tcc.c 
Hello, script language C.

Aber ist das richtig für die C-Sprache?

$ gcc -Wall ./hello_tcc.c 
./hello_tcc.c:1:2: error: invalid preprocessing directive #!
 #!/usr/bin/tcc -run
  ^

Immerhin führt die Shebang-Linie zu einem Fehler. Es kann nur mit TCC kompiliert werden.

Vorschlag 2: Fügen Sie einfach das Ausführungsattribut hinzu

Wenn es eine Shebang-Zeile gibt, wird diese nicht in C-Sprache angezeigt. Löschen Sie sie daher.

hello_x.c(Ausführungsattribute hinzufügen)


#include <stdio.h>
int main (int argc, char* argv[]) {
	printf("Hello, script language C.\n");
	return 0;
}

Es ist nur noch eine Textdatei, aber es ist nicht so, dass sie im Voraus bezahlt wird.

Wenn von der Shell ausgeführt

$ chmod +x hello_x.c
$ ./hello_x.c
./hello_x.c: 2: ./hello_x.c: Syntax error: "(" unexpected

Sie erhalten einen Syntaxfehler. Überprüfen Sie das Verhalten der Shell, um festzustellen, was diesen Fehler verursacht.

$ #(Weil die vorliegende Umgebung Linux ist`strace`Auf Befehl)
$ strace -f sh -c './hello_x.c'

Auszug aus der Strace-Ausgabe


[pid 20349] execve("./hello_x.c", ["./hello_x.c"], [/* 80 vars */]) = -1 ENOEXEC (Exec format error)
[pid 20349] execve("/bin/sh", ["/bin/sh", "./hello_x.c"], [/* 80 vars */]) = 0

Ich habe zwei Zeilen verwandter Teile extrahiert. execve bietet die grundlegendsten Funktionen der Unix exec-Funktionen. Unter Linux usw. ist dies ein Systemaufruf wie er ist, daher erscheint er in "strace".

Shell-Verhalten 1: Führen Sie . / Hello_x.c aus → Fehler

Zuerst starte ich . / Hello_x.c mit execve und erhalte eine Fehlermeldung.

  • ENOEXEC:
    Die ausführbare Datei konnte aufgrund eines unverständlichen Formats, einer anderen Architektur oder eines anderen Formatfehlers nicht ausgeführt werden.

Textdateien ohne Shebang können nicht auf "Ausführen" ausgeführt werden.

Shell-Verhalten 2: Führen Sie die Shell selbst aus

Unmittelbar nachdem ich . / Hello_x.c nicht ausgeführt habe, führe ich mich selbst ( sh) mit . / Hello_x.c als Argument aus (wie dieses Verhalten erreicht werden kann, hängt von der Shell ab). In einigen Situationen verwenden Sie möglicherweise nicht execve). Dies ist das in den Shell-Spezifikationen angegebene Verhalten.

If the execve() function fails due to an error equivalent to the [ENOEXEC] error, the shell shall execute a command equivalent to having a shell invoked with the command name as its first operand, with any remaining arguments passed to the new shell —— Shell Command Language

Übersetzung: Wenn die Funktion execve () aufgrund eines Fehlers fehlschlägt, der dem Fehler [ENOEXEC] entspricht, führt die Shell denselben Befehl aus, der die Shell mit dem Befehlsnamen als erstem Operanden aufruft, und die verbleibenden Argumente sind Es wird an die neue Shell übergeben.

Da . / Hello_x.c jedoch kein Shell-Skript ist, verursacht es einen Syntaxfehler, was bedeutet, dass der obige Fehler angezeigt wird.

Bei Ausführung von einem anderen Programm als der Shell

Es stellt sich heraus, dass eine Datei, die ohne Shebang in der Shell ausgeführt wird, von der Shell selbst als Shell-Skript ausgeführt wird. Aber was ist, wenn es von einem anderen Programm ausgeführt wurde?

$ chmod +x ./hello_x.c
$ env ./hello_x.c 
./hello_x.c: 2: ./hello_x.c: Syntax error: "(" unexpected

Das Obige ist ein Beispiel für den Befehl "env", jedoch mit dem gleichen Ergebnis wie das Ausführen in einer Shell. Dies liegt daran, dass einige der exec-Funktionen dasselbe wie die Shell tun.

Wenn der Header der Datei nicht als ausführbar erkannt wird (die Execve (2), die Sie aufrufen möchten, schlägt mit dem Fehler ENOEXEC fehl), werden diese Funktionen die Datei als erstes Argument (/ bin / sh) schälen. )

Programme wie die Shell, die nach Befehlen in der Umgebungsvariablen "PATH" suchen, verwenden diese Funktionen häufig oder werfen sie von Anfang an in die Shell. Deshalb, ** "Dateien mit Ausführungsattributen, aber ohne Shebang sind nicht sicher, werden aber normalerweise an die Shell übergeben und als Shell-Skript ausgeführt." ** Es sieht gut aus zu sagen.

Vorschlag 3: Quelldatei, die sowohl C-Sprache als auch Shell-Skript ist

Im vorherigen Plan stellte sich heraus, dass die C-Sprache so wie sie war als Shell-Skript ausgeführt wurde und ein Fehler auftrat. Sie müssen sich nur einen Code vorstellen, der die folgenden Bedingungen erfüllt.

C-Sprach-Präprozessor-Direktiven beginnen mit "#". Wir nutzen dies als Kommentar in Shell-Skripten.

hello_c_and_sh.c


#undef SHELL_SCRIPT_CODE
#ifdef SHELL_SCRIPT_CODE
exec tcc -run "$0" "$@"
#endif

#include <stdio.h>
int main (int argc, char* argv[]) {
	printf("Hello, script language C.\n");
	return 0;
}

Bei Ausführung als Shell-Skript wechselt exec zur TCC-Ausführung, sodass nachfolgender C-Sprachcode nicht ausgeführt wird. Bei der Interpretation als C-Sprache ist SHELL_SCRIPT_CODE undef, sodass der Shell-Skriptteil immer übersprungen wird. Kann als Skript ausgeführt werden

$ chmod +x hello_c_and_sh.c
$ ./hello_c_and_sh.c 
Hello, script language C.

Es ist auch eine Quelldatei in C-Sprache, die normal kompiliert werden kann.

$ gcc -Wall ./hello_c_and_sh.c 
$ ./a.out 
Hello, script language C.

Ich habe TCC verwendet, weil es kurz geschrieben werden kann, aber ich habe auch versucht, einen Compiler zu unterstützen, der etwas häufiger vorkommt.

#undef SHELL_SCRIPT_CODE
#ifdef SHELL_SCRIPT_CODE
command -v tcc >/dev/null 2>/dev/null && exec tcc -run "$0" "$@"

tmp_execute="$(mktemp /tmp/tmp_execute.XXXXXX)"
c99 -o "$tmp_execute" "$0"
"$tmp_execute" "$@"
exit_code="$?"
rm "$tmp_execute"
exit "$exit_code"
#endif

#include <stdio.h>
int main (int argc, char* argv[]) {
	printf("Hello, script language C.\n");
	return 0;
}

Wenn es keine TCC gibt, kompilieren, ausführen, löschen Sie die ausführbare Datei usw. mit c99. Wenn Sie sicherstellen möchten, dass die in / tmp / erstellte ausführbare Datei gelöscht wird, müssen Sie möglicherweise etwas mehr entwickeln, diese wird jedoch vorerst abgeschlossen sein.

Lizenz für diesen Artikel

[Creative Commons License](http://creativecommons.org/licenses/by-sa/4.0/ deed.ja) Dieser Artikel wurde unter CC BY-SA 4.0 (Creative Commons Attribution 4.0 Inheritance International License) veröffentlicht.

Recommended Posts

Skriptsprache C - Wie wird eine Textdatei ohne Shebang ausgeführt?
Verwenden Sie eine Skriptsprache für ein komfortables C ++ - Leben
Erstellen Sie eine Datei, die in der Skriptsprache ausgeführt werden kann
So zeigen Sie das Änderungsdatum einer Datei in C-Sprache bis zu Nanosekunden an
So implementieren Sie vorläufig einen Fortschrittsbalken in einer Skriptsprache
Verwenden Sie eine Skriptsprache für ein komfortables C ++ - Leben - OpenCV-Port Python zu C ++ -
Exportieren Sie eine komprimierte gzip-Textdatei
[C-Sprache] So erstellen, vermeiden und erstellen Sie einen Zombie-Prozess
Ich habe viel recherchiert, wie Python ausgeführt wird
So erstellen Sie eine Konfigurationsdatei
Verwenden wir eine Skriptsprache für ein komfortables C ++ - Leben. 2 Generieren Sie automatisch eine C ++ - Quelle
Verwenden wir die Skriptsprache für ein komfortables C ++ - Leben. 4 - Verwenden wir die eigene C ++ - Bibliothek aus der Skriptsprache. -
Verwenden Sie eine Skriptsprache für ein komfortables C ++ - Leben. 3-Überlassen Sie die grafische Darstellung matplotlib-
Was ist eine C-Sprachbibliothek? Welche Informationen sind für die Öffentlichkeit zugänglich?
[C Sprache] Meine Lokomotive ist zu langsam ~ Ich habe einen Sl-Befehl gegeben ~