Sauberer Weg, um eine Konfigurationsdatei vorübergehend zu ersetzen?

7

Ich verwende ein Zeichenprogramm namens Inkscape, das sowohl eine GUI als auch eine Befehlszeilenschnittstelle hat. Bei Verwendung in der Befehlszeile stehen zahlreiche Optionen zur Verfügung, die nur über eine benutzerspezifische Konfigurationsdatei gesteuert werden können, die fest codiert ist:

$HOME/.config/inkscape/preferences.xml

Diese Konfigurationsdatei enthält immer die Optionen, die zuletzt in der GUI verwendet wurden. Diese können beim Erstellen von Skripten falsch sein.

Um dies zu umgehen, muss mein Skript eine Kopie der Konfigurationsdatei speichern, durch eine Standardkonfigurationsdatei ersetzen, das Programm ausführen und dann die gespeicherte Konfigurationsdatei zurückkopieren.

Dies funktioniert in Ordnung, ist aber nicht wirklich sauber. Beispielsweise funktioniert es nicht ordnungsgemäß, wenn zwei Instanzen des Skripts gleichzeitig ausgeführt werden.

Gibt es unter Unix eine sauberere Möglichkeit, diese Aufgabe des Fälschens eines Programms auszuführen, sodass die Konfigurationsdatei von einem gewünschten Ort stammt und nicht von dem im Programm fest codierten Pfadnamen? Vielleicht etwas mit Links oder so etwas wie BSD-Gefängnisse?

Ben Crowell
quelle

Antworten:

9

Inkscape bietet hierfür eine Funktion ab 0.47 :

$ INKSCAPE_PORTABLE_PROFILE_DIR=/some/other/path inkscape --args

Fügen Sie die benutzerdefinierte preferences.xmlDatei Ihres Skripts ein /some/other/path. Es sollte ein dediziertes Verzeichnis sein, da Inkscape es mit allen anderen Dateien füllt, die es normalerweise einfügt, ~/.config/Inkscapewenn Sie es so ausführen.

Warren Young
quelle
Sie können also mehrere Versionen ausführen, indem Sie vor dem Ausführen einfach eine andere Variable angeben, oder? Übrigens gut schleudern!
slm
1
@slm: Ja. Hier wird die Umgebungsvariable eher wie eine Befehlszeilenoption verwendet, da sie nur die einzelne ausgeführte Instanz betrifft. Und ich habe es gefunden, indem ich die Quelle gelesen habe. :)
Warren Young
@ BenCrowell - danke, ich habe einen Kommentar hinterlassen, in dem erwähnt wird, dass es diese versteckte Umgebung gibt. Eine Variable in den offiziellen Dokumenten hätte Ihnen und uns eine ganze Menge Zeit gespart.
slm
7

Da es sich bei Inkscape um eine FOSS- Software handelt, können wir dem Programm einfach eine Option hinzufügen, mit der Sie den Namen einer anderen Konfigurationsdatei wie folgt übergeben können:

=== geänderte Datei 'src / inkscape.cpp'
--- src / inkscape.cpp 28.09.2013 19:20:27 +0000
+++ src / inkscape.cpp 2013-11-02 04:07:45 +0000
@@ -1443,6 +1443,12 @@
             prefdir = g_strdup (val);
         }}

+ // Akzeptiere auch eine Überschreibung über die Kommandozeile
+ extern gchar * sp_preferences;
+ if (sp_preferences) {
+ prefdir = sp_preferences;
+}
+
 #ifdef HAS_SHGetSpecialFolderLocation
         // bevorzuge c: \ Dokumente und Einstellungen \ Benutzername \ Anwendungsdaten \ gegenüber
         // c: \ Dokumente und Einstellungen \ Benutzername \;

=== geänderte Datei 'src / main.cpp'
--- src / main.cpp 24.09.2013 18:31:44 +0000
+++ src / main.cpp 2013-11-02 04:05:30 +0000
@ -179,6 +179,7 @@
     SP_ARG_VERB_LIST,
     SP_ARG_VERB,
     SP_ARG_SELECT,
+ SP_ARG_PREFERENCES,
     SP_ARG_LAST
 };

@@ -228,6 +229,7 @@
 statisch gboolean sp_query_all = FALSE;
 statisch gchar * sp_query_id = NULL;
 statisch gboolean sp_shell = FALSE;
+ gchar * sp_preferences = NULL;
 statisch gboolean sp_vacuum_defs = FALSE;
 #ifdef WITH_DBUS
 statisch gboolean sp_dbus_listen = FALSE;
-520,6 +522,11 @@
      N _ ("Startet Inkscape im interaktiven Shell-Modus."),
      NULL},

+ {"Einstellungen", 0,
+ POPT_ARG_STRING, & sp_preferences, SP_ARG_PREFERENCES,
+ N _ ("Geben Sie eine andere Datei" settings.xml "an."),
+ NULL},
+
     POPT_AUTOHELP POPT_TABLEEND
 };

Ich würde aus zwei Gründen nicht erwarten, dass die Inkscape-Entwickler diesen Patch akzeptieren. Erstens haben sie bereits eine alternative Funktion mit dem gleichen Effekt. Aber zweitens würde ich nicht erwarten, dass ihnen die Art und Weise gefällt, wie ich sp_preferencesprogrammglobal statt modulglobal gemacht habe. Diese Art von Code eignet sich für eine persönliche Funktion, die Sie jedoch nicht als Teil der Hauptsoftware verwenden möchten.

Der obige Patch mag für einen Nicht-Programmierer oder einen, der nicht mit C ++ und Patch-Dateien vertraut ist, ziemlich hässlich aussehen , aber glauben Sie mir, dies ist ungefähr so ​​einfach wie Änderungen an der Software. Es sind nur 10 Zeilen neuen Codes.

(Wenn Sie selbst zählen und 13 neue Zeilen erstellen, sind drei davon leer oder haben nur eine geschweifte Klammer, sodass Sie diese nicht in die SLOC- Zählung einbeziehen .)

Warren Young
quelle
Die Verwendung einer alternativen Konfigurationsdatei sollte eine Befehlszeilenoption sein, aber inkscape scheint dies nicht zu haben. Seltsam.
Faheem Mitha
@FaheemMitha: Die Entscheidung der Inkskape-Entwickler, dies als Umgebungsvariable zu implementieren, ist praktisch dasselbe. Es ist nicht falsch, nur eine andere Stilwahl. Wenn Sie jedoch die Befehlszeilenoption der Umgebungsvariablen vorziehen, haben Sie jetzt meinen Patch, den Sie unverändert übernehmen oder darauf aufbauen können.
Warren Young
Ich denke, beide Möglichkeiten sind möglich und können nebeneinander existieren.
Faheem Mitha
1

Sie könnten symbolische Links verwenden. Legen Sie die Konfigurationsdatei, die Sie mit Ihrer GUI verwenden, irgendwo ab, nennen Sie sie GUI_CONFIG und die mit Skripten für SCRIPT_CONFIG. Setzen Sie am Anfang Ihres Skripts die Zeile:

ln -sf SCRIPT_CONFIG $HOME/.config/inkscape/preferences.xml

und am Ende:

ln -sf GUI_CONFIG $HOME/.config/inkscape/preferences.xml

Wenn das Skript ausgeführt wird, wird preferences.xmlein symbolischer Link erstellt, der auf die benötigte Konfiguration verweist. Wenn es fertig ist, zeigt es auf das zurück, das die GUI verwendet. Wenn Sie mehrere Skripte gleichzeitig ausführen, wird Ihre Konfiguration nicht zerstört, wie dies beim Kopieren von temporären Dateien der Fall ist. Wenn Sie jedoch das erste Skript ausführen, wird die Konfigurationsdatei für noch laufende Skripts beschädigt. Es ist vielleicht am besten, die Anrufe auf lndie einzelnen Anrufe in Inkscape anstatt auf die Skripte als Ganzes zu verteilen, um zu versuchen, diese Rennbedingungen zu verhindern.

Eine andere Möglichkeit wäre, Inkscape als einen anderen Benutzer als Skripte auszuführen, damit Sie es mit einer anderen Konfigurationsdatei einrichten können. Sie müssen sich dann jedoch mit Berechtigungen befassen, möglicherweise indem Sie Dateien hin und her kopieren /tmp.

wingedsubmariner
quelle
1
Dies ist kaum besser als das Kopieren von Dateien und trägt nicht dazu bei, das Problem tatsächlich zu lösen. Der aktuelle fest codierte Pfad in Inkscape ermöglicht es mehreren Programmen, sich gegenseitig zu stören.
Warren Young
1
Wenn Sie die lnOption nicht aus Ihrer Antwort heraus bearbeiten möchten , sollten Sie zumindest die Option "anderer Benutzer" als separate Antwort veröffentlichen. Ich könnte das alleine bewerten, aber nicht, wenn ich an die lnAntwort gebunden bin .
Warren Young
1
Die Aufrufe von lnsind idempotent, sodass er sich keine Sorgen machen muss, seine Konfigurationsdateien zu zerstören oder sie nach Abschluss aller Prozesse in einem unerwünschten Zustand zu belassen. Es verengt das Fenster für Rennbedingungen und macht sie weniger streng.
Wingedsubmariner
1

Wenn Sie in der Dokumentation nach dem Einstellungssubsystem in Inkscape suchen, ist dies nicht möglich.

Deine Optionen:

  1. Tu was du tust
  2. Spiele über das Verknüpfen der Datei spielen
  3. Benutzer eine andere Benutzer-ID
  4. Ändern Sie die Quelle (siehe @ WarrenYoung's Antwort dazu!)
slm
quelle
Ich verstehe nicht, wie Sie zu Ihrer ersten Schlussfolgerung kommen. Diese Seite sagt mir, dass das Programm bereits eine Möglichkeit hat, einen anderen Pfad unter Windows als unter Linux zu übergeben. Sie müssen lediglich eine dritte Datenquelle für den Pfad bereitstellen, die über die Befehlszeile abgerufen wird. Wenn OP kein C-Programmierer ist, suchen Sie einen. Sie sind reichlich vorhanden. :)
Warren Young
@WarrenYoung - nun, es ist derzeit keine Möglichkeit, da es unter Linux steht, zumindest laut den Dokumenten. Ich wollte nicht implizieren, dass die Funktionalität nicht in Inkscape vergraben war und eine Änderung der Quelle nicht einfach oder möglich wäre, nur dass derzeit keine Schalter verfügbar sind.
slm
@WarrenYoung - meldest du dich freiwillig, um dies für ihn zu modifizieren?
slm
Wäre dies überhaupt eine Diskussion, wenn dies eine Konfigurationsdatei /etcanstelle eines C-Programms wäre? Was ist der wesentliche Unterschied? Ist es nur die Tatsache, dass eine Bearbeitung schwieriger ist? Wenn ja, warum wirkt sich das darauf aus, ob meine Antwort eine Antwort ist?
Warren Young
1
@WarrenYoung Ihre Antwort ist sicherlich eine gültige Antwort, aber so würde die Antwort, dass OP ein Kernelmodul schreiben sollte, um Bindungs-Mounts pro Prozess zu ermöglichen, damit er Inkspace dazu verleiten kann, seine Konfigurationsdatei aus einem anderen Verzeichnis zu lesen. Wenn Sie diese Funktion für ihn in Inkscape codieren, sind Sie natürlich weit über die Pflicht hinausgegangen :)
wingedsubmariner