Nixos
如何使現有 Nix 包中的二進製文件能夠在另一個包中執行 shell 腳本?
我目前正在打包一個列印機驅動程序,它使用一個 shell 腳本作為 CUPS 過濾器。顯然,CUPS 需要能夠執行該腳本。但是,目前,它在嘗試時給了我一個 exec 格式錯誤。shell 腳本以
#!/bin/sh
shebang 開頭。包的以下程式碼將非常醜陋/hacky,因為我對 Nix 的了解非常基礎,所以提前抱歉。如果您想提供改進建議,請繼續,但我現在最關心的是如何讓它工作。
with import <nixpkgs> {}; let srcs = { lpr-deb = fetchurl { url = "http://download.brother.com/welcome/dlf101620/mfc9332cdwlpr-1.1.3-0.i386.deb"; sha256 = "0mmqcwpbw4dx2hqaxhnvm52jm84vq8c55xrixsvapxwrdbpkdcca"; name = "mfc9332cdwlpr-1.1.3-0.i386.deb"; }; cupswrapper-deb = fetchurl { url = "http://download.brother.com/welcome/dlf101621/mfc9332cdwcupswrapper-1.1.4-0.i386.deb"; sha256 = "1q9y90hdrgl80zwqk2vn7b1znjvf15l8q0zg868sv0by6rdq8r5w"; name = "mfc9332cdwcupswrapper-1.1.4-0.i386.deb"; }; }; in stdenv.mkDerivation rec { name="brother-mfc9332cdw"; rev = "1.1.4-0"; buildInputs = [ pkgs.wget pkgs.dpkg pkgs.perl pkgs.bash ]; unpackPhase = '' dpkg-deb -x ${srcs.lpr-deb} . dpkg-deb -x ${srcs.cupswrapper-deb} . ''; dontBuild = true; installPhase = '' perl -i -pe 's#printcap\.local#printcap#g' opt/brother/Printers/mfc9332cdw/inf/setupPrintcapij cp -rf usr $out/ cp -rf opt $out/ mkdir -p $out/share/cups/model/Brother cp $out/opt/brother/Printers/mfc9332cdw/cupswrapper/brother_mfc9332cdw_printer_en.ppd $out/share/cups/model/Brother chmod 644 $out/share/cups/model/Brother/brother_mfc9332cdw_printer_en.ppd cat $out/opt/brother/Printers/mfc9332cdw/cupswrapper/cupswrappermfc9332cdw | sed -n "/ENDOFWFILTER/,/ENDOFWFILTER/p" | tail -n +2 | sed "$ d" > brother_lpdwrapper_mfc9332cdw perl -i -pe 's#/usr/#$out/#g' brother_lpdwrapper_mfc9332cdw && perl -i -pe 's#/opt/#$out/opt/#g' brother_lpdwrapper_mfc9332cdw cat <<!ENDOFWFILTER! > brother_lpdwrapper_mfc9332cdw #!/bin/sh # # Copyright (C) 2005-2016 Brother. Industries, Ltd. # Ver1.10 # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the Free # Software Foundation; either version 2 of the License, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # this program; if not, write to the Free Software Foundation, Inc., 59 Temple # Place, Suite 330, Boston, MA 02111-1307 USA # LOGFILE="/dev/null" LOGLEVEL="1" LOGCLEVEL="7" DEBUG=0 NUPENABLE=1 LOG_LATESTONLY=1 touch /tmp/mfc9332cdw_latest_print_info chmod 600 -R /tmp/mfc9332cdw_latest_print_info errorcode=0 if [ \$DEBUG != 0 ]; then LOGFILE=/tmp/br_cupsfilter_debug_log fi PPDC=\`printenv | grep "PPD="\` PPDC=\`echo \$PPDC | sed -e 's/PPD=//'\` if [ "\$PPDC" = "" ]; then PPDC="$out/share/cups/model/Brother/brother_mfc9332cdw_printer_en.ppd" fi if [ \$LOGFILE != "/dev/null" ]; then if [ \$LOG_LATESTONLY == "1" ]; then rm -f \$LOGFILE date >\$LOGFILE else if [ -e \$LOGFILE ]; then date >>\$LOGFILE else date >\$LOGFILE fi fi echo "arg0 = \$0" >>\$LOGFILE echo "arg1 = \$1" >>\$LOGFILE echo "arg2 = \$2" >>\$LOGFILE echo "arg3 = \$3" >>\$LOGFILE echo "arg4 = \$4" >>\$LOGFILE echo "arg5 = \$5" >>\$LOGFILE echo "arg6 = \$6" >>\$LOGFILE echo "PPD = \$PPD" >>\$LOGFILE fi cp $out/opt/brother/Printers/mfc9332cdw/inf/brmfc9332cdwrc /tmp/brmfc9332cdwrc_\$$ chmod 777 -R /tmp/brmfc9332cdwrc_\$$ export BRPRINTERRCFILE=/tmp/brmfc9332cdwrc_\$$ INPUT_TEMP_PS=\`mktemp /tmp/br_input_ps.XXXXXX\` nup="cat" if [ "\`echo \$5 | grep 'Nup='\`" != "" ] && [ \$NUPENABLE != 0 ]; then if [ "\`echo \$5 | grep 'Nup=64'\`" != "" ]; then nup="psnup -64" elif [ "\`echo \$5 | grep 'Nup=32'\`" != "" ]; then nup="psnup -32" elif [ "\`echo \$5 | grep 'Nup=25'\`" != "" ]; then nup="psnup -25" elif [ "\`echo \$5 | grep 'Nup=16'\`" != "" ]; then nup="psnup -16" elif [ "\`echo \$5 | grep 'Nup=8'\`" != "" ]; then nup="psnup -8" elif [ "\`echo \$5 | grep 'Nup=6'\`" != "" ]; then nup="psnup -6" elif [ "\`echo \$5 | grep 'Nup=4'\`" != "" ]; then nup="psnup -4" elif [ "\`echo \$5 | grep 'Nup=2'\`" != "" ]; then nup="psnup -2" elif [ "\`echo \$5 | grep 'Nup=1'\`" != "" ]; then nup="cat" fi echo "NUP=\$nup" >>\$LOGFILE if [ -e /usr/bin/psnup ]; then if [ \$# -ge 7 ]; then cat \$6 | \$nup > \$INPUT_TEMP_PS else cat | \$nup > \$INPUT_TEMP_PS fi else if [ \$# -ge 7 ]; then cp \$6 \$INPUT_TEMP_PS else cat > \$INPUT_TEMP_PS fi fi else if [ \$# -ge 7 ]; then cp \$6 \$INPUT_TEMP_PS else cat > \$INPUT_TEMP_PS fi fi if [ -e "$out/opt/brother/Printers/mfc9332cdw/lpd/filtermfc9332cdw" ]; then : else echo "ERROR: /opt/brother/Printers/mfc9332cdw/lpd/filtermfc9332cdw does not exist" >>\$LOGFILE echo "ERROR: /opt/brother/Printers/mfc9332cdw/lpd/filtermfc9332cdw does not exist" >>/tmp/mfc9332cdw_latest_print_info errorcode=30 exit fi CUPSOPTION=\`echo "\$5 Copies=1" | sed -e 's/BrMirror=OFF/MirrorPrint=OFF/' -e 's/BrMirror=ON/MirrorPrint=ON/' -e 's/BrChain/Chain/' -e 's/BrBrightness/Brightness/' -e 's/BrContrast/Contrast/' -e 's/BrHalfCut/HalfCut/' -e 's/BrAutoTapeCut/AutoCut/' -e 's/BrHalftonePattern/Halftone/' -e 's/Binary/Binary/' -e 's/Dither/Dither/' -e 's/ErrorDiffusion/ErrorDiffusion/' -e 's/BrSheets/Sheets/' -e 's/multiple-document-handling/Collate/' -e 's/separate-documents-collated-copies/ON/' -e 's/separate-documents-uncollated-copies/OFF/'\` if [ -e "$out/opt/brother/Printers/mfc9332cdw/cupswrapper/brcupsconfpt1" ]; then if [ \$DEBUG = 0 ]; then $out/opt/brother/Printers/mfc9332cdw/cupswrapper/brcupsconfpt1 MFC9332CDW \$PPDC 0 "\$CUPSOPTION" "mfc9332cdw" \$BRPRINTERRCFILE>> /dev/null else $out/opt/brother/Printers/mfc9332cdw/cupswrapper/brcupsconfpt1 MFC9332CDW \$PPDC \$LOGCLEVEL "\$CUPSOPTION" "mfc9332cdw" \$BRPRINTERRCFILE>>\$LOGFILE fi fi if [ \$DEBUG -lt 10 ]; then cat \$INPUT_TEMP_PS | $out/opt/brother/Printers/mfc9332cdw/lpd/filtermfc9332cdw echo brmfc9332cdwrc_\$$ > /tmp/mfc9332cdw_latest_print_info cat /tmp/brmfc9332cdwrc_\$$ >> /tmp/mfc9332cdw_latest_print_info rm -f /tmp/brmfc9332cdwrc_\$$ if [ \$LOGLEVEL -gt 2 ]; then if [ \$LOGFILE != "/dev/null" ]; then echo "" >>\$LOGFILE echo " ------PostScript Data-------" >>\$LOGFILE cat \$INPUT_TEMP_PS >>\$LOGFILE fi fi fi rm -f \$INPUT_TEMP_PS exit $errorcode !ENDOFWFILTER! chmod 755 brother_lpdwrapper_mfc9332cdw mkdir -p $out/lib/cups/filter cp brother_lpdwrapper_mfc9332cdw $out/lib/cups/filter ''; }
我正在談論的 bash 腳本是用
cat
in設置的installPhase
(我知道,非常抱歉,但這實際上只是他們在原始兄弟安裝腳本中所做的修改版本,所以這是我的藉口)。此外,這是 CUPS 日誌的相關部分:
Jan 29 15:43:22 kenix-vaio cupsd[11674]: Started filter /nix/store/v0vlk9dni6kn077i3ilfkml4cr8w979b-cups-progs/lib/cups/filter/pdftopdf (PID 11799) Jan 29 15:43:22 kenix-vaio cupsd[11674]: Started filter /nix/store/v0vlk9dni6kn077i3ilfkml4cr8w979b-cups-progs/lib/cups/filter/pdftops (PID 11800) Jan 29 15:43:22 kenix-vaio cupsd[11674]: Started filter /nix/store/v0vlk9dni6kn077i3ilfkml4cr8w979b-cups-progs/lib/cups/filter/brother_lpdwrapper_mfc9332cdw (PID 11801) Jan 29 15:43:22 kenix-vaio cupsd[11674]: Started backend /nix/store/v0vlk9dni6kn077i3ilfkml4cr8w979b-cups-progs/lib/cups/backend/lpd (PID 11802) Jan 29 15:43:22 kenix-vaio cupsd[11674]: REQUEST localhost - - POST /printers/MFC9332CDW HTTP/1.1 200 127388 Send-Document successful-ok Jan 29 15:43:22 kenix-vaio cupsd[11674]: execv failed: Exec format error Jan 29 15:43:22 kenix-vaio cupsd[11674]: PID 11801 (/nix/store/v0vlk9dni6kn077i3ilfkml4cr8w979b-cups-progs/lib/cups/filter/brother_lpdwrapper_mfc9332cdw) stopped with status 108 (Exec format error)
您錯誤地生成了過濾器腳本。每行(特別是第一行)都縮進兩個空格。這意味著您的
#!/bin/sh
行實際上是..#!/bin/sh
(我用點來表示空格),這意味著核心無法理解您的意思,從而產生exec format error
.您將所有內容縮進兩個空格,所以我建議更改此行
cat <<!ENDOFWFILTER! > brother_lpdwrapper_mfc9332cdw ... !ENDOFWFILTER!
對於這個
sed 's/^ //' <<'!ENDOFWFILTER!' > brother_lpdwrapper_mfc9332cdw ... !ENDOFWFILTER!
當您在那裡時,引用的此處結束標記將確保您包含的此處文本也被引用,因此您無需
$
使用反斜杠轉義和其他重要字元。