Portable bináris függőségeit tartalmazó csomagok

 ( TCH | 2018. január 15., hétfő - 20:14 )

Adott egy futtatható bináris, amit nem csomagkezelőből telepítettünk. Nem akar elindulni a hiányzó függőségek miatt, de mivel nem csomagból van így a szükséges csomagokat max. úgy lehet összeszedni, hogy objdump-pal kiolvassuk a libeket, aztán egyesével megnézetjük a csomagkezelővel, hogy melyik csomag tartalmazza azt. Ezt én most automatizáltam magamnak (Debian-ra), akinek kell viheti, átírhatja másik csomagkezelőre, mittudomén...

#!/bin/sh

if [ ! -f "$1" ]; then
	echo "Usage: lsdeppkg "
	exit
fi

DISTRO=`cat /etc/*-release | awk -F '"' '/NAME/ {print $2; exit}'`
TMP=$(mktemp /tmp/deplst-XXXXXX)
PKGS=""
objdump -p "$1" | grep "NEEDED" > "$TMP"
while IFS= read -r file; do
	file=`echo "$file" | awk -F ' ' '{print $2}'`
	if [ "$DISTRO" == "Arch Linux" ]; then
		PKG=`pacman -Fsq "$file"`
		if [ "$PKG" != "" ]; then
			PKG=`echo "$PKG" | head -1`
		fi
	else
		PKG=`dpkg -S "$file" 2>/dev/null`
		if [ "$PKG" != "" ]; then
			PKG=`echo "$PKG" | cut -f1 -d":"`
		fi
	fi
	if [ "$PKG" == "" ]; then
		(>&2 echo "$file: No match.")
	else
		PKGS="$PKGS$PKG\n"
	fi
done < "$TMP"
rm "$TMP"
echo "Packages:"
echo "$PKGS" | sort | uniq | tr '\n' ' '
echo ""

A script az összeszedett csomagokat a végén egybe köpi ki (szóközökkel elválasztva), akár át is lehet dobni a csomagkezelőnek; az olyan libeket viszont menet közben írja ki az stderr-re, amikhez nem talált csomagot.

Építő jellegű javaslatokat szívesen fogadok egyszerűsítésre, optimalizációra, vagy akármi másra.

Sz*rk: zolk3ri kolléga már küldött is egy patchet, amiben a temp fájl nevét mktemp-pel állítja elő és az Arch pacman-jét is támogatja.

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

en az ldd-t szoktam hasznalni...

--
t-systems-es it architect allast keres. Jelige: csak webshopot ne kelljen...

Nem biztos, hogy az jó ötlet, két okból is: Egyrészt az ldd hajlamos elindítani a programot, hogy kiderítse a függőségeit (ami egy harmadik féltől származó programnál nem feltétlen jó ötlet), másrészt az ldd rekurzívan vizsgálja a függőségeket, azaz nem csak a program által linkelt objektumokat listázza, hanem azokat is, amik már az SO-kban vannak linkelve, ez pedig azzal fog járni, hogy a csomagkezelőnek egy jóval nagyobb listában kell keresnie, hogy melyik csomag tartalmazza az adott libet, ami megsokszorozza a futásidőt, ráadásul értelmetlen, hiszen ha a program által linkelt objektumok csomagjait megkaptuk, akkor azok a csomagok úgyis magukkal fogják húzni a függőségeiket és velük együtt azokat a libeket, amikre a a program által linkelt libek linkelnek.

"hajlamos elindítani a programot" ? :o

~~~~~~~~
deb http://deb.uucp.hu/ wheezy yazzy repack

A megfogalmazás talán pongyola és szakmaiatlan volt, de nagyjából erről van szó:

#man ldd

---

ldd kiírja a parancssorban megadott program futtatásához szükséges
megosztott könyvtárakat.

Az a.out programoknál az ldd egyszerűen egy fork és egy exec
segítségével az argc-nek nullát megadva elindítja a programot. Az a.out
dinamikus linkere, az ld.so, amely normálisan betölti a megosztott
könyvtárakat, észreveszi ezt a speciális indítást, és kiírja a
szükséges könyvtárakat.

ELF programoknál az ldd egy fork és egy exec segítségével elindítja a
programot, és beállít egy megfelelő környezeti változót. Az ELF
dinamikus linker, az ld-linux.so, amely normálisan a megosztott
könyvtárakat betölti, észreveszi ezt a speciális esetet és kiírja a
futtatáshoz szükséges könyvtárak listáját.

Nem az volt az eredeti problemad, hogy nem hajlando elindulni a program? Most akkor miert baj, ha megis elindul? :)

Nekem nem volt semmiféle problémám, csak publikáltam egy scriptet, ami egy program csomagfüggőségeit szedi össze. Egyébként a nagyobbik probléma az ldd-vel amúgyis a rekurzió volt...

Gyakran teszel fel ismeretlen forrasbol szarmazo binarist?

Ha egy program nincs benne a repoban (ez azert Debianban eleg nagy, marmint a repo), akkor jon a forrasbol forditas. Az meg amugy is elarulja, hogy milyen fuggosegei vannak (mindenfele -dev csomagot fel kell rakni, aztan hajra).

Ha meg zart forrasu, akkor vagy csomagot adnak, vagy valami installer scriptet, ami ezeket elrendezi idealis esetben.

--
Any A.I. smart enough to pass a Turing test is smart enough to know to fail it. -Ian McDonald

Itt az utóbbi esetről van inkább szó; nem minden eset ideális.

Tehát valami bináris trutty, amit nem debilkére készítetek el eredetileg, csak ugye minden, ai nem debilke, az fúj... :-P

Én hol mondtam ilyet? Én azt használok, ezért arra írtam meg, de azért publikáltam, hogy más meg átírhassa amire akarja. (Egyébként mindenhova jó, ahol van dpkg, nem csak a debilányra.) Lentebb már ki is bővítették Arch-ra. Köszi a rosszindulatot.

Nem rosszindulat, csak gyakran bele lehet olyasmibe futni,hogy valamit elkészítenek RHEL/CentOS vonalra, aztán de alapú rendszerre "azérisfelszögeljükmertazrpmyumfúj" alapon csak azért is felszögeljük - és ekkor szokott előkerülni az, hogy oké, de az x, y, z... akármi függőséget honnan, melyik csomagból lehet fellapátolni.

Aki meg targézéből vagy más csomagkezelőn kívüli módon rak fel sz@rul-vagy-sehogy dokumentált olyan motyót, aminek így kell megkeresni a függőségeit, nos, az magára vessen...

Én nem fikáztam egyik rendszert sem; megírtam arra, ami nekem van és publikáltam, akinek kell átírja magának, nem ez volna a nyílt forrás egyik lényege?

Mondod te. Én meg megoldottam magamnak.

Én sem fikáztam, de ott, ahol ilyen "reszeljükkimertazajó" kell, hogy működjön, ott más is káosz kapitány titkos felügyelete alatt leledzik...

Én egy előfordulható problémára adtam megoldást, akinek nem kell, nem használja, ilyen egyszerű. Ennek a meddő vitának semmi értelme.

Olyan problémára, ami döntően "worst practice" esetben fordul elő.

Van olyan, hogy nincs választás, mert mondjuk a gyártói hozzáállás olyan. A problémát megoldani kell, nem rinyálni fölötte, hogy ez a rossz gyakorlat eredménye. Ennyi.

Melyik gyártó az, ami ad-hoc buildel valamit úgy, hogy se CentOS/RHEL se Debian/Ubuntu vonalon nincs kijelölt támogatott OS, és a lomjának perverz, nem dokumentált függőségei vannak? Nehezen hihető, hogy csak úgy kiböffent valaki egy binárist Linuxra, nulla leírással a használat feltételeiről, függőségeiről...

Noname távolkeleti pl.


#!/bin/sh

if [ ! -f "$1" ]; then
echo "Usage: lsdeppkg "
exit
fi

DISTRO=`cat /etc/*-release | awk -F '"' '/NAME/ {print $2; exit}'`
TMP=`mktemp /tmp/deplst-XXXXXX`
PKGS=""
objdump -p "$1" | grep "NEEDED" > "$TMP"
while IFS= read -r file; do
file=`echo "$file" | awk -F ' ' '{print $2}'`
if [ "$DISTRO" == "Arch Linux" ]; then
PKG=`pacman -Fsq "$file" 2>/dev/null | head -1`
else
PKG=`dpkg -S "$file" 2>/dev/null | cut -f1 -d":"`
fi
if [ $? -eq 0 ]; then
if [ "$PKGS" == "" ]; then
PKGS="$PKG"
else
PKGS="$PKGS\n$PKG"
fi
else
(>&2 echo "$file: No match.")
fi
done < "$TMP"
rm "$TMP"
echo "Packages:"
echo -e "$PKGS" | sort | uniq | tr '\n' ' '
echo ""

Igen, igen, tudom, úgy tűnik, hogy a code tag nem elég a helyes formázáshoz.
Tudna valaki segíteni? 8 éve vagyok itt, de még egyszer sem szúrtam be kódot. :P

Én a blockquote tag-et használtam az indentálásra, mert nekem se ment rendesen.

Gondolom mivel közvetlen a hozzászolásomra válaszoltál, ezért már nem engedi szerkeszteni. Az usage text is problémás a kódban, no mindegy. :D

Sorry.

Az usage text meg relációs jelek közt van, amit HTML kódnak néz, azokat jobb beírni &lt; és &gt; kódokkal.

Igen, gondoltam, de már nem tudtam módosítani. :D

Mindegy, a lényeg gondolom átment, hogy jobb ilyen esetben mktemp-et használni, hogy ne okozzon problémát a script többszöri párhuzamos futtatása, például ha több user használná egy időben, vagy több binárison akarod futtatni egyszerre, aminek persze a valószínűsége elhanyagolható.

Arch Linux támogatást kiegészítésképpen adtam hozzá, hátha valakinek szüksége van rá.

Igen, jogos az mktemp, köszi!

Beraktam a beküldött részeket a szkriptbe, fennt a blogpostban is. :)

Feltételeztem, hogy a cut -f1 -d":" azért kell, mert a dpkg outputja megköveteli, ezért ezt beraktam a dpkg-vel azonos sorba, tehát még egyszer futtatni felesleges, de azért jó lenne, ha tesztelnéd. :D

Amit még változtattam az a következő:

if [ "$PKGS" == "" ]; then
    PKGS="$PKG"
else
    PKGS="$PKGS\n$PKG"
fi

ami csak arra jó, hogy a $PKGS elején ne legyen egy felesleges \n majd később ebből egy szóköz.

Hopsz, az most esik le, hogy az úgy nem jó, sem a dpkg, sem a pacman sorában sem, hiszen ha átadod a csövön keresztül a végeredményt egy másik programnak, akkor utána a $?-ben nem a csomagkezelő, hanem a másik program, a cut és a head visszatérési értékei lesznek... Az nem véletlen volt különválasztva. Beraktam, hogy miután megvan a végeredmény, a kapott szöveget a disztrónak megfelelően dolgozza fel. Ha van jobb ötleted, ne tartsd magadban.

A leading space eltakarítására én inkább ezt találtam ki:

PKGS="$PKGS$PKG\n"

Így ugyan trailing space lesz, na de az meg kit zavar, cserébe mínusz egy elágazás, egyszerűbb a kód.

Jogos, viszont úgy tűnik, hogy pacman -Fsq visszatérési értéke mindig 0, függetlenül attól, hogy a fájlt megtalálta-e vagy sem.

Esetleg így lehetne megoldani Arch Linux esetében:

PKG=`pacman -Fsq "$file"`

if [ -z "$PKG" ]; then
    (>&2 echo "$file: No match.")
else
    PKG=`echo "$PKG" | head -1`
fi

vagy [ "$PKG" == "" ], nekem mindegy. :D

Beleraktam, de kicsit összekombináltam. Mindkettőnél megnézzük, hogy üres-e és ha az, akkor levágjuk, amit le kell, majd a végén a script még egyszer ellenőrzi, hogy van-e valami a PKG változóban és ha nincs, akkor error, ha van, akkor listába vele.

PKG=`dpkg -S "$file" 2>/dev/null | cut -f1 -d":" ; exit ${PIPESTATUS[0]}`

if [ $? -eq 0 ]; then

~~~~~~~~
deb http://deb.uucp.hu/ wheezy yazzy repack

Köszi a tippet, de ehhez megint újra kéne a ciklus belsejét szervezni. A mostani meg szerintem elég univerzális már, hogy akár egyéb csomagkezelőket is bele lehessen tenni.

a másik zárójeles verzió :-)

ez egy
   behúzásokkal
teli
   és mégis szépen formázott
kódblokk

szerk.: fordítva (a szögletes zárójeles a jó), de nekem is ki kellett próbálnom.

...és tényleg! Köszönöm! :D

Thx!

sub
### ()__))____________)~~~ ########################
# "Do what you want, but do it right" # X220/Arch

sub
--
TH