| RPM-LUA(7) | Miscellaneous Information Manual | RPM-LUA(7) |
BEZEICHNUNG¶
rpm-lua - in RPM eingebetteter Lua-Interpreter
ÜBERSICHT¶
%scriptlet -p <lua>
%{lua:…}
BESCHREIBUNG¶
Lua ist eine universelle Programmiersprache, die speziell für die Einbettung in andere Programme entwickelt wurde. RPM enthält einen eingebetteten Lua-Interpreter für die Verwendung in erweiterten rpm-macros(7) und Transaktions-Scriptlets.
Der eingebettete Lua-Interpreter ermöglicht verschiedene Dinge, die mit einfachen Makros oder externen Shell-Skripten schwierig oder unmöglich sind, beispielsweise die Beseitigung von Abhängigkeitsschleifen aus Paket-Scriptlets.
MAKROS¶
Zugriff auf Makros¶
Die rpm-Erweiterung bietet verschiedene Funktionen für den Umgang mit Makros. Der bequemste Weg, aus der RPM-Lua-Umgebung auf rpm-macroproc(7) zuzugreifen, ist jedoch über die globale macros-Tabelle.
Lua unterscheidet nicht zwischen Tabellenindex- und Feldnamensyntax, daher sind macros.foo und macros['foo'] gleichwertig. Verwenden Sie, was besser zum Zweck passt.
Wie bei jeder echten Lua-Tabelle werden nicht vorhandene Elemente als nil zurückgegeben. Zuweisungen können zum Definieren oder Aufheben der Definition von Makros verwendet werden.
Beispiel:
if not macros.yours then
macros.my = 'my macro' end local v = { '_libdir', '_bindir', '_xbindir' } for _, v in ipairs(v) do
if not macros[v] then
macros[v] = 'default'
end end
Alle Makros nutzen dieselbe globale Lua-Ausführungsumgebung.
Aufruf parametrischer Makros¶
Parametrische Makros (einschließlich aller eingebauten Makros) können Lua-nativ über die macros-Tabelle aufgerufen werden, entweder mit der Syntax macros.Name() oder macros[Name]().
Argumente werden über ein einzelnes Argument übergeben, das entweder
- eine einzelne Zeichenfolge, die in diesem Fall mit den makro-nativen Regeln expandiert und aufgeteilt wird,
- oder eine Tabelle ist. In diesem Fall werden die Tabelleninhalte als wörtliche Argumente verwendet, die in keiner Weise erweitert werden.
Beispiel 1:
macros.with('foo')
Beispiel 2:
macros.dostuff({'one', 'two', 'three'})
Zurückliefern von Daten¶
Per Definition landet alles, was in Lua mit print() aufgerufen wird, in der Makroerweiterung. Lua-Makros können ihre Ausgabe auch mit return ausgeben, wodurch Hilfsmakros für die Programmierung natürlicher aussehen.
Beispiel:
%sum() %{lua:
local v = 0
for _, a in ipairs(arg) do
v = v + tonumber(a)
end
return v
}
Optionen und Argumente¶
Parametrische Lua-Makros erhalten ihre Optionen und Argumente als zwei lokale Tabellen opt und arg, wobei opt verarbeitete Optionswerte enthält, dessen Position (Tabellenschlüssel) durch das Optionszeichen bestimmt wird, und arg numerisch indizierte Argumente enthält.
Diese Tabellen sind immer vorhanden, unabhängig davon, ob Optionen oder Argumente tatsächlich übergeben wurden, um die Verwendung zu vereinfachen.
Beispiel:
%foo(a:b) %{lua:
if opt.b then
print('do b')
else
print('or not')
end
if opt.a == 's' then
print('do s')
end
if #arg == 0 then
print('no arguments :(')
else
for i = 1, #arg do
print(arg[i])
end
end
}
SCRIPTLETS¶
Das interne Lua kann als Interpreter von RPM für alle Transaktionsscriptlets verwendet werden, einschließlich Triggern und Dateitriggern:
Beispiel:
%pre -p <lua>
print('Hello from Lua')
Während das bewährte /bin/sh für paketbezogene Skriptaktivitäten in der Regel praktischer ist, bietet der eingebettete Lua-Interpreter einige einzigartige Vorteile für Transaktionsscriptlets: Den Paketen werden keine zusätzlichen Abhängigkeiten hinzugefügt, was dazu beiträgt, Abhängigkeitsschleifen zu vermeiden. Das kann beim frühen »Bootstrap«-Paketsatz bei einer Erstinstallation ein entscheidender Unterschied sein.
Insbesondere ist ein eingebettetes Lua-Skript die einzige allgemein nutzbare Option in %pretrans-Skripten während der Erstinstallation eines Systems.
Eingebettetes Lua ist außerdem viel schneller als die Ausführung eines möglicherweise schwergewichtigen Interpreters, nur um ein paar Zeilen Shell-Skript auszuführen.
Hinweis: Scriptlets, die das interne Lua verwenden, sollten keine Annahmen über die gemeinsame Nutzung der Ausführungsumgebung mit anderen Scriptlets treffen.
Argumente¶
Scriptlet-Argumente sind über eine globale arg-Tabelle zugänglich.
Hinweis: In Lua beginnen Indizes üblicherweise bei 1 (eins) statt bei 0 (null), und die RPM-Implementierung folgt dieser Vorgehensweise, ob nun gut oder schlecht. Daher weichen die Indizes der Scriptlet-Argumente um eins von der allgemeinen Erwartung ab, die auf traditionellen Scriptlet-Argumenten basiert. Das Argument, das die Anzahl der installierten Paketinstanzen enthält, ist arg[2], und das ähnliche Argument für Triggerziele ist arg[3], im Gegensatz zu den traditionellen $1 und $2 in Shell-Skripten.
Beispiel:
%postun -p <lua> if arg[2] == 0 then
print("erasing") end
Verschiebbare Pakete¶
Scriptlets verschiebbarer Pakete enthalten zusätzlich eine globale RPM_INSTALL_PREFIX-Tabelle, die alle möglichen Präfixe des Pakets enthält.
Hinzugefügt: 4.18.0
Rückgabewert¶
Obwohl Scriptlets normalerweise nicht fehlschlagen dürfen, können Sie den Scriptlet-Fehlerstatus bei Bedarf mit der Lua-Funktion error(Meldung, [Stufe]) signalisieren.
SPEC-DATEIEN¶
Im Kontext einer rpm-spec(5)-Dateianalyse mit rpmbuild(1) oder rpmspec(1) enthält die RPM-Lua-Umgebung die folgenden .spec-abhängigen globalen Tabellen:
patches
patch_nums
sources
source_nums
Beispiel:
for i, p in ipairs(patches) do
print(string.format("echo %d: %sn", patch_nums[i], patches[i])) end
ERWEITERUNGEN¶
Zusätzlich zu den Lua-Standardbibliotheken (abhängig von der Lua-Version, gegen die RPM gelinkt ist) sind die folgenden Erweiterungen im internen Lua-Interpreter von RPM verfügbar. Diese können in allen Kontexten verwendet werden, in denen auch das interne Lua verwendet werden kann.
RPM-Erweiterung¶
Die folgenden RPM-spezifischen Funktionen sind verfügbar:
b64decode(Argument)
Beispiel:
blob = 'binary data' print(blob) e = rpm.b64encode(blob) print(e) d = rpm.b64decode(e) print(d)
b64encode(Argument [, Zeilenlänge])
define("Name Textkörper")
Beispiel:
rpm.define('foo 1')
execute(Pfad [, Argument1 [,…])
Für eine bessere Kontrolle über die Prozessausführung und die Ausgaben, siehe rpm.spawn().
Hinzugefügt: 4.15.0
Beispiel:
rpm.execute('ls', '-l', '/')
Beispiel:
rpm.expand('%{_libdir}/mydir')
glob(Muster, [Schalter])
Beispiel:
for i, p in ipairs(rpm.glob('*')) do
print(p)
end
interactive()
Beispiel:
rpm --eval "%{lua: rpm.interactive()}"
isdefined(Makro)
Beispiel:
if rpm.isdefined('_libdir') then
…
end
load(Pfad)
Beispiel:
rpm.load('my.macros')
open(Pfad, [Modus[.Schalter]])
Der Pfad ist eine Zeichenkette mit dem Dateinamen, der optional eine Modus-Zeichenkette folgt, die den Geöffnet-Status angibt:
- a: zum Anhängen geöffnet
- w: zum Schreiben geöffnet; abgeschnitten
- r: zum Lesen geöffnet (Vorgabe)
- +: zum Lesen und Schreiben geöffnet
- x: schlägt fehl, wenn die Datei existiert
Darauf folgen optional die Nutzdaten-Schalter (siehe rpm-payloadflags(7)) für Komprimierung und Dekomprimierung.
Hinzugefügt: 4.17.0
Beispiel:
f = rpm.open('some.txt.gz', 'r.gzdio')
print(f:read())
Das zurückgelieferte rpm.fd-Objekt verfügt über die folgenden Methoden:
fd:close()
Schließt den Datenstrom.
Beispiel:
f = rpm.open('file')
f:close()
fd:flush()
Leert den Datenstrom.
Beispiel:
f = rpm.open('file', 'w')
f:write('foo')
f:flush()
f:close()
fd:read([Position])
Liest Daten aus dem Datenstrom bis zu der angegebenen Byte-Position. Falls diese nicht angegeben ist, wird die gesamte Datei gelesen.
Beispiel:
f = rpm.open('/eine/Datei')
print(f:read())
fd:seek(Modus, Versatz)
Positioniert den Datei-Versatz des Datenstroms neu. Der Modus ist einer aus set, cur oder end. Der Versatz ist relativ zur aktuellen Position: absolut, relativ zum aktuellen Modus oder relativ zum Ende. Nicht alle Datenströme unterstützen das Durchsuchen.
Gibt den Dateiversatz nach der Aktion zurück.
Siehe auch lseek(3).
Beispiel:
f = rpm.open('neuedatei', 'w')
f:seek('set', 555)
f:close()
fd:write(Puffer [, Länge])
Schreibt Daten im Puffer in den Datei-Datenstrom, entweder vollständig oder bis zu der Länge Byte, falls angegeben.
Beispiel:
f = rpm.open('neuedatei', 'w')
f:write('data data')
f:close()
fd:reopen(Modus)
Öffnet einen Datenstrom mit einem neuen Modus erneut (siehe rpm.open()).
Beispiel:
rpm.open('irgendein.txt.gz')
f = f:reopen('r.gzdio')
print(f:read())}
redirect2null(Nummer) (VERALTET)
Diese Funktion ist veraltet und nur noch zwecks Abwärtskompatibilität für RPM-Pakete der Version 4 verfügbar. Verwenden Sie stattdessen rpm.spawn() oder rpm.execute().
pid = posix.fork() if pid == 0 then
posix.redirect2null(2)
assert(posix.exec('/bin/awk')) elseif pid > 0 then
posix.wait(pid) end
spawn({Befehl} [, {Aktionen}])
Der {Befehl} ist eine Tabelle, die aus dem Befehl und dessen Argumenten besteht. Eine optionale zweite Tabelle kann verwendet werden, um verschiedene Aktionen im Zusammenhang mit der Befehlsausführung zu übergeben. Derzeit werden folgende unterstützt:
| Aktion | Argument(e) | Beschreibung |---------|--------------------------- | *stdin* | Pfad | Standardeingabe zum Pfad umleiten | *stdout*| Pfad | Standardausgabe zum Pfad umleiten | *stderr*| Pfad | Standardfehlerausgabe zum Pfad umleiten
Gibt den Exit-Status des Befehls zurück: Null bei Erfolg oder ein Tripel aus (nil, Meldung, Code) bei Fehlschlag.
Hinzugefügt: 4.20
Beispiel:
rpm.spawn({'systemctl', 'restart', 'httpd'}, {stderr='/dev/null'})
undefine(Name)
Beachten Sie, dass nur die aktuellste Makrodefinition mit dem angegebenen Namen vom Stapel entfernt wird. Das heißt, dass nach einer solchen Aktion zum Zurücksetzen noch Makrodefinitionen mit demselben Namen vorhanden sein können.
Beispiel:
rpm.undefine('zzz')
vercmp(v1, v2)
Hinweis: In RPM-Versionen vor 4.16 wurde dies nur auf Versionssegmente angewendet, was bei vollständigen EVR-Zeichenketten keine korrekten Ergebnisse liefert.
Beispiel:
rpm.vercmp('1.2-1', '2.0-1')
ver(evr), ver(e, v, r)
Hinzugefügt: 4.17.0
Beispiel:
v1 = rpm.ver('5:1.0-2)
v2 = rpm.ver(3, '5a', 1)
if v1 < v2 then
…
end
if v1.e then
…
end
POSIX-Erweiterung¶
Die Lua-Standardbibliothek bietet einen relativ begrenzten Satz an E/A-Operationen. Die posix-Erweiterung verbessert die Möglichkeiten von Lua erheblich.
Die folgenden Funktionen sind im posix-Namensraum verfügbar. Um sie aufzurufen, verwenden Sie posix.function(). Diese Dokumentation konzentriert sich auf die Lua-API-Konventionen. Weitere Informationen zu den entsprechenden Systemaufrufen finden Sie im Systemhandbuch, z.B. access(3) für posix.access().
access(Pfad [, Modus]B)
- r: lesbar
- w: schreibbar
- x: ausführbar
- f: existiert
Beispiel:
if posix.access('/bin/rpm', 'x') then
…
end
chdir(Pfad)
Beispiel:
posix.chdir('/tmp')
chmod(Pfad, Modus)
Beispiel:
posix.chmod('aa', 600)
posix.chmod('bb', 'rw-')
posix.chmod('cc', 'u+x')
chown(Pfad, Benutzer, Gruppe)
Hinweis: Diese Aktion erfordert Administratorrechte.
Beispiel:
posix.chown('aa', 0, 0)
posix.chown('bb', 'nobody', 'nobody')
ctermid()
dir([Pfad])
Beispiel:
for i,p in pairs(posix.dir('/')) do
print(p..'n')
end
errno()
Beispiel:
f = '/zzz' if not posix.chmod(f, 100) then
s, n = posix.errno()
print(f, s) end
exec(Pfad [, Argumente …]) (VERALTET)
Diese Funktion ist veraltet und nur noch zwecks Abwärtskompatibilität für RPM-Pakete der Version 4 verfügbar. Verwenden Sie stattdessen rpm.spawn() oder rpm.execute().
files([Pfad])
Beispiel:
for f in posix.files('/') do
print(f..'n')
end
fork() (VERALTET)
Diese Funktion ist veraltet und nur noch zwecks Abwärtskompatibilität für RPM-Pakete der Version 4 verfügbar. Verwenden Sie stattdessen rpm.spawn() oder rpm.execute().
Beispiel:
pid = posix.fork() if pid == 0 then
posix.exec('/foo/bar') elseif pid > 0 then
posix.wait(pid) end
getcwd()
Beispiel:
if posix.getcwd() ~= '/' then
… endif
getenv(Name)
Beispiel:
if posix.getenv('HOME') ~= posix.getcwd() then
print('not at home')
end
getgroup(Gruppe)
Beispiel:
print(posix.getgroup('wheel').gid)
getlogin()
getpasswd([Benutzer [, Auswahloption]])
- name
- uid
- gid
- dir
- shell
- gecos
- passwd
Falls weggelassen, wird eine Tabelle mit allen diesen Feldern zurückgeliefert.
Beispiel:
pw = posix.getpasswd(posix.getlogin(), 'shell')|
getprocessid([Auswahloption])
- egid: effektive Gruppen-ID
- euid: effektive Benutzer-ID
- gid: Gruppen-ID
- uid: Benutzer-ID
- pgrp: ID der übergeordneten Gruppe
- pid: ID des übergeordneten Benutzers
- ppid: die der pid übergeordnete ID
Falls weggelassen, wird eine Tabelle mit allen diesen Feldern zurückgeliefert.
Beispiel:
if posix.getprocessid('pid') == 1 then
…
end
kill(PID [, signal])
Beispiel:
posix.kill(posix.getprocessid('pid'))
link(alter-Pfad, neuer-Pfad)
Beispiel:
f = rpm.open('aaa', 'w')
posix.link('aaa', 'bbb')
mkdir(Pfad)
Beispiel:
posix.mkdir('/tmp')
mkfifo(Pfad)
Beispiel:
posix.mkfifo('/tmp/badplace')
pathconf(Pfad [, Auswahloption])
- link_max
- max_canon
- max_input
- name_max
- path_max
- pipe_buf
- chown_restricted
- no_trunc
- vdisable.
Falls weggelassen, wird eine Tabelle mit allen diesen Feldern zurückgeliefert.
Beispiel:
posix.pathconf('/', 'path_max')
putenv(Zeichenkette)
Beispiel:
posix.putenv('HOME=/me')
readlink(Pfad)
Beispiel:
posix.mkdir('aaa')
posix.symlink('aaa', 'bbb')
print(posix.readlink('bbb'))
rmdir(Pfad)
setgid(Gruppe)
Hinweis: Diese Aktion erfordert Administratorrechte.
setuid(Benutzer)
Hinweis: Diese Aktion erfordert Administratorrechte.
Beispiel:
posix.setuid('nobody')
sleep(Dauer)
stat(Pfad [, Auswahloption])
- mode
- ino
- dev
- nlink
- uid
- gid
- size
- atime
- mtime
- ctime
- type.
Falls weggelassen, wird eine Tabelle mit allen diesen Feldern zurückgeliefert.
Beispiel:
print(posix.stat('/tmp', 'mode'))|
s1 = posix.stat('f1')
s2 = posix.stat('f2')
if s1.ino == s2.ino and s1.dev == s2.dev then
…
end
symlink(alter-Pfad, neuer-Pfad)
Beispiel:
posix.mkdir('aaa')
posix.symlink('aaa', 'bbb')
sysconf([Auswahloption])
- arg_max
- child_max
- clk_tck
- ngroups_max
- stream_max
- tzname_max
- open_max
- job_control
- saved_ids
- version.
Falls weggelassen, wird eine Tabelle mit allen diesen Feldern zurückgeliefert.
Beispiel:
posix.sysconf('open_max')|
times([Auswahloption])
- utime
- stime
- cutime
- cstime
- elapsed
Falls weggelassen, wird eine Tabelle mit allen diesen Feldern zurückgeliefert.
Beispiel:
t = posix.times() print(t.utime, t.stime)
ttyname([Dateideskriptor])
Beispiel:
if not posix.ttyname() then
… endif
umask([Modus])
Beispiel:
print(posix.umask())
posix.umask(222)
posix.umask('ug-w')
posix.umask('rw-rw-r--')
uname(Format)
- %m: Name des Hardwaretyps
- %n: Name dieses Knotens
- %r: Aktuelle Veröffentlichungsstufe dieser Implementierung
- %s: Name dieses Betriebssystems
- %v: Aktuelle Versionsstufe dieser Implementierung
Beispiel:
print(posix.uname('%s %r'))
utime(Pfad [, mtime [, ctime]])
Falls mtime oder ctime weggelassen werden, wird die aktuelle Zeit verwendet, ähnlich wie bei touch(1).
Beispiel:
posix.mkdir('aaa')
posix.utime('aaa', 0, 0)
wait([PID]) (ALS VERALTET MARKIERT)
Diese Funktion ist veraltet und nur noch zwecks Abwärtskompatibilität für RPM-Pakete der Version 4 verfügbar. Verwenden Sie stattdessen rpm.spawn() oder rpm.execute().
Beispiel:
pid = posix.fork() if pid == 0 then
posix.exec('/bin/ls')) elseif pid > 0 then
posix.wait(pid) end
setenv(Name, Wert [, Überschreibung])
Beispiel:
posix.setenv('HOME', '/me', true)
unsetenv(Name)
Beispiel:
posix.unsetenv('HOME')
ERWEITERUNG UND ANPASSUNG¶
Bei der Initialisierung führt RPM ein globales Lua-Initialisierungsskript init.lua aus dem Verzeichnis aus, in das %getconfdir expandiert, typischerweise /usr/lib/rpm/init.lua. Damit kann die RPM-Lua-Umgebung angepasst werden, ohne RPM neu kompilieren zu müssen.
Für den eingebetteten Lua-Interpreter werden mit require geladene Module primär in %{getconfdir}/lua/ gesucht. %_rpmluadir ist eine Abkürzung für diesen Pfad.
SIEHE AUCH¶
rpm-macros(7), rpm-payloadflags(7), rpmlua(1), rpm-version(7)
ÜBERSETZUNG¶
Die deutsche Übersetzung dieser Handbuchseite wurde von Mario Blättermann <mario.blaettermann@gmail.com> erstellt.
Diese Übersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer bezüglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen.
Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an die Mailingliste der Übersetzer: debian-l10n-german@lists.debian.org.
| 7. November 2025 | RPM 6.0.0 |