“ Argumenttiluettelo liian pitkä ”: Kuinka käsittelen sitä muuttamatta komentoani?

Kun suoritan komennon, kuten ls */*/*/*/*.jpg, saan virheen

-bash: /bin/ls: Argument list too long 

Tiedän miksi näin tapahtuu: se johtuu siitä, että komennon argumenteille on varattu ytimen raja. Tavallinen ohje on vaihtaa käyttämäni komento, jotta vältetään niin paljon tilaa argumenteille (esim. find ja xargs).

Entä jos en halua muuttaa komentoa? Entä jos haluan jatkaa saman komennon käyttöä? Kuinka voin saada asiat ”toimimaan” ilman virheitä? Mitkä ratkaisut ovat käytettävissä?

kommentit

  • Hyödyllistä tietoa: Bashin usein kysytyt kysymykset 95 . Muuttamatta komentoa siellä ' ei ole paljon muuta, mitä voit tehdä uudelleen kääntämisen lisäksi argumenttiluettelon enimmäiskoon lisäämiseksi tai hakemistorakenteen muuttamiseksi siten, että tiedostoja on vähemmän.
  • @ jw013 linux-ytimen version perusteella voi olla mahdollista lisätä argumenttiluetteloa – katso lisätietoja muutoksesta unix.stackexchange.com/a/45161/8979 uusimmat järjestelmät.
  • @UlrichDangel, Yup, se on mahdollista! Katso vastaukseni; vastaukseni näyttää, miten se tehdään (L inux, riittävän äskettäisellä ytimellä).

vastaus

Linuxissa komentojen enimmäistila argumentit ovat 1/4 käytettävissä olevan pinotilan määrästä. Joten ratkaisu on lisätä pinon käytettävissä olevan tilan määrää.

Lyhyt versio: suorita jotain

ulimit -s 65536 

Pidempi versio : Pinoa varten käytettävissä oleva oletusarvo on noin 8192 kt. Näet käytettävissä olevan tilan määrän seuraavasti:

$ ulimit -s 8192 

Valitse suurempi numero ja aseta pinolle käytettävissä oleva tila. Jos esimerkiksi haluat yrittää sallia pinolle jopa 65536 kt, suorita tämä:

$ ulimit -s 65536 

Saatat joutua pelaamaan, kuinka suurta tätä tarvitaan olla käyttämällä kokeiluvirheitä. Monissa tapauksissa tämä on nopea ja likainen ratkaisu, joka poistaa tarpeen muuttaa komentoa ja selvittää find, xargs jne. (vaikka ymmärrän, että sillä on muita etuja).

Uskon, että tämä on Linux-kohtainen. Epäilen, että se todennäköisesti ei auta missään muussa Unix-käyttöjärjestelmässä (ei testattu).

Kommentit

  • Voit varmistaa näin, että se toimi : $ getconf ARG_MAX 2097152 $ ulimit -s 65535 $ getconf ARG_MAX 16776960
  • Tarkoittaako tämä sitä, että jos teen pinokoon rajoittamattomaksi ulimit -s unlimited -toiminnolla, komentorivin koko on rajoittamaton?

Vastaa

ls */*/*/*/*.jpg sijaan kokeile:

echo */*/*/*/*.jpg | xargs ls 

xargs (1) tietää, mikä on järjestelmän enimmäismäärä argumentteja, ja hajottaa vakiotulonsa kutsumaan määritettyä komentoriviä useita kertoja ilman enempää argumentteja kuin tämä raja, riippumatta siitä, mikä se on (voit myös asettaa sen alhaisemmaksi kuin käyttöjärjestelmän ”suurin” -n vaihtoehto).

Oletetaan esimerkiksi, että raja on 3 argumenttia ja sinulla on viisi tiedostoa. Tällöin xargs suorittaa ls kahdesti:

  1. ls 1.jpg 2.jpg 3.jpg
  2. ls 4.jpg 5.jpg

Usein tämä sopii täydellisesti, mutta ei aina – esimerkiksi et voi luottaa siihen, että ls (1) lajittelee kaikki merkinnät sinulle oikein, koska kukin erillinen ls -kutsu lajittelee vain sille xargs antamien merkintöjen osajoukon.

Vaikka voit kaataa rajan muiden suosittelemalla tavalla, raja on silti olemassa – ja jonain päivänä JPG-kokoelmasi kasvaa uudestaan. Sinun tulisi valmistautua käsikirjoituksesi käsittelemään ääretön määrä …

Kommentit

  • Kiitos ideasta! Tämä ei ole huono kiertotapa. Kaksi varoitusta: 1. Tämä rikkoo hakemistot ja tiedostonimet, joiden nimessä on välilyöntejä, joten se ' ei ole täydellinen korvike. 2. Onko kyse samasta ongelmasta Argument list too long kanssa, mutta echo -kohdassa ls, kuoreissa, joissa echo ei ole kuoren sisäänrakennettu komento? (Ehkä se ' ei ole ongelma useimmissa kuoreissa, joten ehkä ' ei ole merkitystä.)
  • Kyllä , tiedostonimien erikoismerkit ovat ongelma. Parasta panostasi on käyttää find predikaatin -print0 kanssa – ja liittää sen lähtö xargs vaihtoehdolla -0.echo on sisäänrakennettu kuori eikä kärsi komentorivirajoituksesta exec (3).
  • Tämä toimii komentojen kanssa, jotka odottavat muuttujan argumenttia viimeisenä parametrina, kuten ls, mutta mitä teen, kun haluan mv monta tiedostoa yhteen hakemistoon, esim mv * destdir? Jos * antaa " liian monta argumenttia " -virheen, voin ' ei saa xargs siirtää polut ensimmäisinä kohtaan mv jollain tavalla, vai voinko?
  • Tarkista järjestelmän sivulta xargs – esimerkiksi FreeBSD: llä -J auttaa sinulle tämän tehtävän kanssa. Jos käyttöjärjestelmässäsi ei ole mitään keinoa tehdä tämä, ' sinun on kirjoitettava oma komentosarja järjestämään argumentit uudelleen. Jotain tällaista: destdir=$1; shift; mv "$@" "$destdir". Anna sitten tämä uusi komentosarja xargs: .... | xargs newscript $destdir

Vastaa

Tässä Linux Journal -artikkelissa on neljä ratkaisua. Vain neljäs ratkaisu ei sisällä komennon muuttamista:

Menetelmässä 4 lisätään manuaalisesti ytimessä allokoitujen sivujen määrää komentoriville perustelut. Jos tarkastelet include / linux / binfmts.h-tiedostoa, löydät sen yläreunasta seuraavat:

/* * MAX_ARG_PAGES defines the number of pages allocated for arguments * and envelope for the new program. 32 should suffice, this gives * a maximum env+arg of 128kB w/4KB pages! */ #define MAX_ARG_PAGES 32 

Muistin määrän lisäämiseksi omistettu komentoriviargumenteille, sinun tarvitsee vain antaa MAX_ARG_PAGES -arvo suuremmalla luvulla. Kun tämä muokkaus on tallennettu, käännä uudelleen, asenna ja käynnistä se uudelle ytimelle tavalliseen tapaan.

Omassa testausjärjestelmässäni onnistuin ratkaisemaan kaikki ongelmani nostamalla tämän arvon 64: een. testauksessa, en ole kokenut yhtään ongelmaa vaihdon jälkeen. Tämä on täysin odotettua, koska vaikka MAX_ARG_PAGES olisi asetettu arvoon 64, pisin mahdollinen komentorivi, jonka voisin tuottaa, vie vain 256 kt järjestelmän muistia – ei kovin paljon nykypäivän järjestelmän laitteistostandardien mukaan .

Menetelmän 4 edut ovat selvät. Pystyt nyt suorittamaan komennon tavalliseen tapaan, ja se suoritetaan onnistuneesti. Haitat ovat yhtä selvät. Jos korotat käytettävissä olevan muistin määrää komentoriville vapaan järjestelmämuistin määrän ulkopuolella, voit luoda DOS-hyökkäyksen omalle järjestelmällesi ja aiheuttaa sen kaatumisen. Erityisesti monen käyttäjän järjestelmissä jopa pienellä lisäyksellä voi olla merkittävä vaikutus, koska jokaiselle käyttäjälle osoitetaan sitten lisää muistia. Siksi testaa aina perusteellisesti omassa ympäristössäsi, koska tämä on turvallisin tapa selvittää, onko menetelmä # 4 sinulle käyttökelpoinen vaihtoehto.

Olen samaa mieltä siitä, että rajoitus on vakavasti ärsyttävä.

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *