Hi there,
dieser Post baut auf einem älteren von mir auf: http://forum.ubuntuusers.de/topic/wine-applikationen-als-deb-am-beispiel-von-te/
Das Thema hat mich nie so richtig verlassen und daher hatte ich vor geraumer Zeit mal ein paar Scripte ausprobiert, die ich hier mit euch teilen und verbessern möchte. Im Prinzip, bin ich fast der Meinung, das man das mit Python besser lösen könnte als mit der bash.
Aufgabe:
Es geht darum einen wineprefix an einen zentralen Ort wie /opt/ zu hinterlegen. Ein Startscript für die Wine-Applikation sorgt dafür, dass im Home-Folder dieselbe Struktur vorliegt. Dateien und Verzeichnisse, welche die Wine-Applikation zum schreiben benötigt oder userspezisische Savegames und Konfigurationsdateien, liegen dabei im Home-Folder physisch vor. Jegliche unveränderliche Dateien werden per Symlink aus /opt/ mit dem Home-Folder verknüpft. Am Ende steht im Home-Folder-Prefix also die komplette Struktur des Wineprefixes inkl. notwendiger schreibrechte. Die Anwendung selber bzw. der Wine-Prefix liegt zentral in /opt/. Die passende Wine-Version liegt ebenfalls zentral. Das Script bindet Wine-Version und Prefix zusammen.
Hat man eine solche funktionierende Struktur, so ist der Weg zu einem Debian-Paket nicht mehr fern. Patches könnten somit für alle zentral über apt-einfließen. Sowohl an wineprefix als auch die wineversion, die genauso passend upgegradet werden könnte. Die Installation über apt brächte noch den Vorteil bestimmte Dialoge zentral erfolgen zu lassen, wie z. B. Zustimmung zu einer Lizenz etc.
Lösungsansatz:
Bevor ich die Scripte poste, folgt hier eine kleine Erläuterung der Herangehensweise an die Lösung der Aufgabe:
Basis bildet eine mittels PlayOnLinux erstellte Installation eines Programms.
Der Wineprefix und die WineVersion werden in eine entsprechende Struktur in /opt/ überführt. In meinem Fall nach folgendem Muster /opt/wineports/<HerstellerDir>/<Programm-Dir>/ . Hierunter werden die Verzeichnisse wine und wineprefix angelegt.
Ein Startscript kümmert sich beim Start ggf. um die Einrichtung einer entsprechenden Home-Folder-Struktur, welche die /opt/ Struktur mittels Symlinks verknüft und schreibbare Verzeichnisse im Home-Folder physisch anlegt.
Die entsprechende Wine-Ausführung und der zugehörige Wineprefix werden in die Umgebungsvariablen geschrieben.
Das Programm wird gestartet.
Beispiel 1 wpstartnpp.sh:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | #!/bin/bash # set basic opt path of application PROG_OPT_DIR="/opt/wineports/NotepadplusplusTeam/Notepadplusplus" PROG_HOME_DIR="$HOME/.wineports/NotepadplusplusTeam/Notepadplusplus" PROG_WINE_DIR="$PROG_OPT_DIR/wine" PROG_WINE_BIN="$PROG_WINE_DIR/bin" # set base environment variables export PATH=$PROG_WINE_BIN:$PATH export LD_LIBRARY_PATH=$PROG_WINE_DIR/lib:$PROG_WINE_DIR/lib/fakedlls:$LD_LIBRARY_PATH export WINEPREFIX="$PROG_HOME_DIR/prefix" export WINEDLLPATH="$PROG_WINE_DIR/lib/wine" export WINELOADER="$PROG_WINE_BIN/wine" export WINESERVER="$PROG_WINE_BIN/wineserver" export PREFIX_PROG_DIR="$WINEPREFIX/drive_c/ProgramFiles/Notepad++/" export OPT_PROG_DIR="$PROG_OPT_DIR/prefix/drive_c/ProgramFiles/Notepad++/" export OPT_SEARCH_DIR=$PROG_OPT_DIR/prefix/drive_c/ProgramFiles/Notepad++/ export WINEPORTS_MAXDEPTH_SEARCH=5 export WINEPORTS_DOS_STARTPATH="c:\ProgramFiles\Notepad++\notepad++.exe" # export WINEPORTS_SHARE_FOLDER="/usr/share/wineports/PiranhaBytes/Gothic/" function SetupHomeEnvironment() { # create symlinks for dosdevices mkdir -p $WINEPREFIX/dosdevices/ local C_LINK="$WINEPREFIX/dosdevices/c:" local C_TARGET="$WINEPREFIX/drive_c/" local Z_LINK="$WINEPREFIX/dosdevices/z:" local Z_TARGET="/" ln -s $C_TARGET $C_LINK ln -s $Z_TARGET $Z_LINK # create basic home folder for placing all symlink-elements in if ! [ -d "$PREFIX_PROG_DIR" ] ; then mkdir -p "$PREFIX_PROG_DIR" fi # search source dir for all folders and subfolders in configured depth # @TODO: Search delivers too much results in subfolders EMPTY_REPLACEMENT="" echo $OPT_SEARCH_DIR echo "find $OPT_SEARCH_DIR -maxdepth $WINEPORTS_MAXDEPTH_SEARCH -type d -print0 -printf \"%h;\"" RecursivePathSearch="$(find $OPT_SEARCH_DIR -maxdepth $WINEPORTS_MAXDEPTH_SEARCH -type d -print0 -printf "%h;")" echo $RecursivePathSearch OrigIFS=$IFS IFS=";" ArrayPathSearch=($RecursivePathSearch) # echo ${ArrayPathSearch[@]} exit 0 COUNTER=0 for CurrentPath in ${ArrayPathSearch[@]} ; do if ! [ -e "$CurrentPath" ] ; then if [ "$COUNTER" != "0" ] ; then # remove opt-path RelativePath="${CurrentPath//$OPT_PROG_DIR/$EMPTY_REPLACEMENT}" # Switched off escaping due it does not create exprected results # EscapedRelativePath=$(echo $RelativePath | sed 's/ /\\ /g') CreateHomePath "$RelativePath" LinkSubpath "$RelativePath" fi let COUNTER=COUNTER+1 fi done IFS=$OrigIFS } function LinkSubpath() { local SubOptPath="$OPT_PROG_DIR$1" local SubHomePath="$PREFIX_PROG_DIR$1" echo $SubOptPath # search files in opt path if opt-path exists and link home links to corresponding opt-files if [ -e "$SubOptPath" ] ; then # echo "find $SubOptPath -maxdepth 1 -type f \( ! -iname \".*\" \) \( ! -iname \"*~\" \) -printf \"%f;\"" FileSearchResult=$(find $SubOptPath -maxdepth 1 -type f \( ! -iname ".*" \) \( ! -iname "*~" \) -printf "%f;") # echo $FileSearchResult OrigIFS=$IFS IFS=";" ArrayFileSearch=($FileSearchResult) COUNTER=0 for CurrentFile in ${ArrayFileSearch[@]} ; do if ! [ -e "$SubHomePath/$CurrentFile" ] ; then echo "ln -s $SubOptPath/$CurrentFile $SubHomePath/$CurrentFile" ln -s $SubOptPath/$CurrentFile $SubHomePath/$CurrentFile fi done IFS=$OrigIFS fi } function CreateHomePath() { local CreatePath="$PREFIX_PROG_DIR$1" if ! [ -d "$CreatePath" ] ; then echo "mkdir -p $CreatePath" mkdir -p $CreatePath fi } function CreatePath() { local CreatePath="$1" if ! [ -d "$CreatePath" ] ; then mkdir -p $CreatePath fi } function CopyConfig() { echo "Copy ini files from share to home folder" } function RunApplication() { winedbg $WINEPORTS_DOS_STARTPATH } CreatePath "$PROG_HOME_DIR" CreatePath "$WINEPREFIX" SetupHomeEnvironment RunApplication |
Beispiel 2 wpstartgothic.sh:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | #!/bin/bash # set basic opt path of application PROG_OPT_DIR="/opt/wineports/PiranhaBytes/Gothic" PROG_HOME_DIR="$HOME/.wineports/PiranhaBytes/Gothic" PROG_WINE_DIR="$PROG_OPT_DIR/wine" PROG_WINE_BIN="$PROG_WINE_DIR/bin" # set base environment variables export PATH=$PROG_WINE_BIN:$PATH export LD_LIBRARY_PATH=$PROG_WINE_DIR/lib:$PROG_WINE_DIR/lib/fakedlls:$LD_LIBRARY_PATH export WINEPREFIX="$PROG_HOME_DIR/prefix" export WINEDLLPATH="$PROG_WINE_DIR/lib/wine" export WINELOADER="$PROG_WINE_BIN/wine" export WINESERVER="$PROG_WINE_BIN/wineserver" export PREFIX_PROG_DIR="$WINEPREFIX/drive_c/Programme/PiranhaBytes/Gothic" export OPT_PROG_DIR="$PROG_OPT_DIR/prefix/drive_c/Programme/PiranhaBytes/Gothic" export WINEPORTS_MAXDEPTH_SEARCH=5 export WINEPORTS_DOS_STARTPATH="c:\Programme\PiranhaBytes\Gothic\system\gothic.exe" export WINEPORTS_SHARE_FOLDER="/usr/share/wineports/PiranhaBytes/Gothic/" function SetupHomeEnvironment() { # create symlinks for dosdevices mkdir -p $WINEPREFIX/dosdevices/ local C_LINK="$WINEPREFIX/dosdevices/c:" local C_TARGET="$WINEPREFIX/drive_c/" local Z_LINK="$WINEPREFIX/dosdevices/z:" local Z_TARGET="/" #local D_LINK="$WINEPREFIX/dosdevices/d:" #local D_TARGET="/media/GOTHIC_CD2/" ln -s $C_TARGET $C_LINK ln -s $Z_TARGET $Z_LINK #ln -s $D_TARGET $D_LINK # create basic home folder for placing all symlink-elements in if ! [ -d "$PREFIX_PROG_DIR" ] ; then mkdir -p "$PREFIX_PROG_DIR" fi # search source dir for all folders and subfolders in configured depth # @TODO: Search delivers too much results in subfolders EMPTY_REPLACEMENT="" RecursivePathSearch="$(find $OPT_PROG_DIR -maxdepth $WINEPORTS_MAXDEPTH_SEARCH -type d -print0 -printf "%h;")" OrigIFS=$IFS IFS=";" ArrayPathSearch=($RecursivePathSearch) COUNTER=0 for CurrentPath in ${ArrayPathSearch[@]} ; do if ! [ -e "$CurrentPath" ] ; then if [ "$COUNTER" != "0" ] ; then # remove opt-path RelativePath="${CurrentPath//$OPT_PROG_DIR/$EMPTY_REPLACEMENT}" # Switched off escaping due it does not create exprected results # EscapedRelativePath=$(echo $RelativePath | sed 's/ /\\ /g') CreateHomePath "$RelativePath" LinkSubpath "$RelativePath" fi let COUNTER=COUNTER+1 fi done IFS=$OrigIFS } function LinkSubpath() { local SubOptPath="$OPT_PROG_DIR$1" local SubHomePath="$PREFIX_PROG_DIR$1" # search files in opt path if opt-path exists and link home links to corresponding opt-files if [ -e "$SubOptPath" ] ; then # echo "find $SubOptPath -maxdepth 1 -type f \( ! -iname \".*\" \) \( ! -iname \"*~\" \) -printf \"%f;\"" FileSearchResult=$(find $SubOptPath -maxdepth 1 -type f \( ! -iname ".*" \) \( ! -iname "*~" \) -printf "%f;") # echo $FileSearchResult OrigIFS=$IFS IFS=";" ArrayFileSearch=($FileSearchResult) COUNTER=0 for CurrentFile in ${ArrayFileSearch[@]} ; do if ! [ -e "$SubHomePath/$CurrentFile" ] ; then ln -s $SubOptPath/$CurrentFile $SubHomePath/$CurrentFile fi done IFS=$OrigIFS fi } function CreateHomePath() { local CreatePath="$PREFIX_PROG_DIR$1" if ! [ -d "$CreatePath" ] ; then mkdir -p $CreatePath fi } function CreatePath() { local CreatePath="$1" if ! [ -d "$CreatePath" ] ; then mkdir -p $CreatePath fi } function CopyConfig() { echo "Copy ini files from share to home folder" } function RunApplication() { winedbg $WINEPORTS_DOS_STARTPATH } CreatePath "$PROG_HOME_DIR" CreatePath "$WINEPREFIX" SetupHomeEnvironment RunApplication |
Der Aufbau ist recht identisch. Die beiden Scripte funktionieren bisher nicht vollständig. Dabei haben beide unterschiedliche Probleme. Dass notepad++-Startscript hat Probleme, die Verzeichnisse korrekt zu ermitteln und das Gothic-Startscript bricht am Ladebildschirm innerhalb von wine ab.
Verbesserungsmöglichkeiten:
Natürlich sind mir schon ein paar Gedanken gekommen, wie man den Ansatz verbessern könnte. Generell denke ich, dass man das ganze viel enger mit PlayOnLinux verzahnen sollte und mehr von der PlayOnLinux-Struktur Gebrauch machen. Also z. B. die Prefixe in der Homestruktur von POL verlinken. Und statt einer Wineversion in /opt/ lediglich die POL-Konfiguration so anzulegen, dass POL die passende Wine-Version prüft und ggf. herunterlädt.
Dass eine zentrale Wine-Installation prinzipiell funktioniert ist unbestritten ( Siehe Teamviewer ), jedoch würde ich mal gern einen generellen, gangbaren Weg ausarbeiten, mit welchem man zentrale Installationen von Wine-Basierter Software ermöglichen könnte.
Hoffe, dass das Thema jemanden von euch interessiert und ihr eure Gedanken und/oder Verbesserungsvorschläge mit mir teilt. Habt ihr vielleicht schon ähnliche Versuche unternommen? Welche sicherheitstechnischen Bedenken habt ihr bei der Symlink-Methode?
Gruß
André