Tyypilliset Unix / Linux-ohjelmat hyväksyvät komentorivin syötteet argumenttien määränä (int argc
) ja argumenttivektorina (char *argv[]
). argv
-elementin ensimmäinen elementti on ohjelman nimi, jota seuraavat todelliset argumentit.
Miksi ohjelman nimi välitetään suoritettavalle tiedostolle argumenttina? Onko olemassa esimerkkejä ohjelmista, jotka käyttävät omaa nimeään (ehkä jonkinlainen exec
tilanne)?
Kommentit
Answer
Huomaa aluksi, että argv[0]
ei välttämättä ole ohjelman nimi. Soittaja asettaa tämän execve
-järjestelmäkutsun argv[0]
-sarjaan (esim. Katso tämä kysymys pinon ylivuotoa ). (Kaikki muut versiot exec
eivät ole järjestelmäkutsuja, vaan liitännät ryhmään execve
.)
Oletetaan esimerkiksi, että seuraava (käyttäen execl
):
execl("/var/tmp/mybackdoor", "top", NULL);
/var/tmp/mybackdoor
on mikä suoritetaan, mutta argv[0]
-asetuksena on top
, ja tämä on ps
tai ( todellinen) top
näytetään. Katso tämä vastaus U & L SE: ltä.
Kaikkien asetusten määrittäminen tämä syrjään: Ennen hienojen tiedostojärjestelmien, kuten /proc
, syntymistä argv[0]
oli ainoa tapa prosessille oppia omasta nimestään. Mille se olisi hyvä?
- Useat ohjelmat mukauttavat käyttäytymistään nimen mukaan, jolla niitä kutsuttiin (yleensä symbolisilla tai kovilla linkeillä, esimerkiksi / div> BusyBoxin apuohjelmat ; useita muita esimerkkejä annetaan muissa vastauksissa tähän kysymykseen).
- Lisäksi syslogin kautta kirjautuvat palvelut, demonit ja muut ohjelmat usein liittävät nimensä lokimerkinnät; ilman tätä tapahtumien seuranta olisi mahdotonta.
Kommentit
- Esimerkkejä tällaisista ohjelmista ovat
bunzip2
,bzcat
jabzip2
, joista kaksi ensimmäistä ovat linkkejä kolmanteen. - @Ruslan Mielenkiintoista, että
zcat
ei ole symboli. He näyttävät välttävän tämän tekniikan haittoja käyttämällä komentotulkkikomentosarjaa. Mutta he eivät pysty tulostamaan täydellistä--help
-lähtö, koska joku, joka lisäsi vaihtoehtoja gzip-tiedostoon, unohti pääsivun tain zcat. - Niin kauan kuin muistan, GNU-koodausstandardit ovat estäneet argv [0]: n käyttöä ohjelman käyttäytymisen muuttamiseksi ( -osio ” Liitäntöjen standardit Yleensä ” nykyisessä versiossa ).
gunzip
on historiallinen poikkeus. - busybox on toinen erinomainen esimerkki. Sitä voidaan kutsua 308 eri nimellä kutsumaan erilaisia komentoja: busybox.net/downloads/BusyBox.html#commands
- monia, monia useampia ohjelmia myös injektoidaan
argv[0]
käyttö- / ohjetulosteeseen nimen koodaamisen sijaan. Jotkut kokonaan, jotkut vain basename.
Vastaa
Runsaasti:
- Bash toimii POSIX-tilassa , kun
argv[0]
onsh
. Se toimii kirjautumiskuorena, kunargv[0]
alkaa-
. - Vim käyttäytyy eri tavalla, kun sitä käytetään nimellä
vi
,view
,evim
,eview
,ex
,vimdiff
jne. - Busybox, kuten jo mainittiin.
- Järjestelmissä, joissa systemd on init,
shutdown
,reboot
jne. Ovat symboloisystemctl
. - ja niin edelleen.
Kommentit
- Toinen on
sendmail
jamail
. Jokaisessa yksittäisessä unix MTA: ssa on symlinkki näille kahdelle komennolle, ja se on suunniteltu jäljittelemään alkuperäistä ’ käyttäytymistä, kun sitä kutsutaan sellaisenaan, mikä tarkoittaa, että kaikki unix-ohjelmat, joiden on lähetettävä sähköpostia, tietävät miten he voivat tehdä niin. - toinen yleinen tapaus:
test
ja[
: kun soitat edelliseen , se käsittelee virheen, jos viimeinen argumentti on]
. (todellisessa Debianin vakaa tilassa nämä komennot ovat kahta erilaista ohjelmaa, mutta aiemmat versiot ja MacO: t käyttävät edelleen samaa ohjelmaa). Jatex
,latex
ja niin edelleen: binääri on sama, mutta katsoen kuinka sitä kutsuttiin, se valitsee oikean kokoonpano tiedosto.init
on samanlainen. - Related,
[
pitää virhenä, jos viimeinen argumentti on ei]
. - Luulen, että tämä vastaa toiseen kysymykseen, mutta ei ensimmäiseen. Epäilen kovasti, että joku käyttöjärjestelmän suunnittelija istui alas ja sanoi » Hei, olisi hienoa, jos minulla olisi sama ohjelma, joka tekisi erilaisia asioita vain sen suoritettavan nimen perusteella. Luulen, että ’ sisällytän nimen sitten argumenttiryhmäänsä. «
- @Joey Kyllä, sanamuoto on tarkoitettu välittämään, että (Q: ” Onko …? ” A: ” Runsaasti: … ”)
vastaus
Historiallisesti argv
on vain joukko osoittimia komentorivin ”sanoille”, joten on järkevää aloittaa ensimmäisellä ”sanalla”, joka satunnaisesti on ohjelman nimi.
Ja on olemassa melko monta ohjelmaa, jotka käyttäytyvät eri tavalla sen mukaan, minkä nimen avulla niitä kutsutaan, joten voit luoda vain erilaisia linkkejä niihin ja saada erilaisia ”komentoja”. äärimmäinen esimerkki, jonka voin ajatella, on väylälaatikko , joka toimii kuin useita kymmeniä erilaisia ”komentoja” sen mukaan, miten sitä kutsutaan .
Muokkaa
: Viitteet Unixin 1. painokseen pyydettäessä
Näet esimerkiksi cc
-toiminnon tärkeimmistä funktioista, jotka argc
ja argv
oli jo käytetty. -kuori kopioi argumentit parbuf
-kansioon newarg
-osan sisällä silmukkaa, kun taas itse komentoa käsitellään samalla tavalla kuin argumentteja. (Tietenkin myöhemmin se suorittaa vain ensimmäisen argumentin, joka on komennon nimi.) Näyttää siltä, että execv
ja sukulaisia ei ollut silloin.
Kommentit
- lisää viitteet, jotka varmuuskopioi tämä.
- Nopeasta skoimisesta
exec
ottaa suoritettavan komennon nimen ja nollapäätteisen taulukon merkkijonoja (näkyy parhaiten kohdassa minnie.tuhs.org/cgi-bin/utree.pl?file=V1/u0.s , missäexec
vie viitteet tunnisteisiin 2 ja 1 ja tunnisteissa2:
näkyyetc/init\0
ja tunnisteissa1:
näyttää viitteen tunnisteeseen 2 ja päättyvän nollan), mikä on periaatteessa mitäexecve
tekee tänään miinusenvp
. -
execv
jaexecl
ovat olleet olemassa ” ikuisesti ” (ts. 1970-luvun alusta puoliväliin) –execv
oli järjestelmäkutsu ja oli kirjastotoiminto, joka kutsui sitä. Tällöinexecve
ei ollut olemassa ’, koska ympäristöä ei ollut silloin olemassa ’. Muut perheenjäsenet lisättiin myöhemmin. - @ G-Man Voitteko osoittaa minut
execv
linkittämääni v1-lähteeseen? Vain utelias.
Vastaa
Käyttötapaukset:
Voit käyttää ohjelman nimeä ohjelman käyttäytymisen muuttamiseen .
Voit esimerkiksi luoda joitain symboleita varsinaiseen binaariin.
Yksi tunnetuimmista esimerkeistä, joissa tätä tekniikkaa käytetään, on busybox-projekti, joka asentaa vain yhden yksittäisen binaarin ja useita symboleita siihen. (ls, cp, mv jne.). He tekevät sen säästääkseen tallennustilaa , koska niiden kohteet ovat pieniä upotettuja laitteita.
Tämä on myös käytetään setarch
-sovelluksessa util-linuxista:
$ ls -l /usr/bin/ | grep setarch lrwxrwxrwx 1 root root 7 2015-11-05 02:15 i386 -> setarch lrwxrwxrwx 1 root root 7 2015-11-05 02:15 linux32 -> setarch lrwxrwxrwx 1 root root 7 2015-11-05 02:15 linux64 -> setarch -rwxr-xr-x 1 root root 14680 2015-10-22 16:54 setarch lrwxrwxrwx 1 root root 7 2015-11-05 02:15 x86_64 -> setarch
Tässä he käyttävät tätä tekniikkaa pohjimmiltaan välttääksesi useita päällekkäisiä lähdetiedostoja tai vain pitääkseen lähteet helpommin luettavissa.
Toinen käyttötapaus olisi ohjelma, joka tarvitsee ladata joitain moduuleja tai tietoja ajon aikana. Ohjelmapolun saaminen antaa sinun ladata moduuleja polulta suhteessa ohjelman sijaintiin .
Lisäksi monet ohjelmat tulostavat virheilmoitukset, mukaan lukien ohjelman nimi .
Miksi :
- Koska se on POSIX-käytäntö (
man 3p execve
):
argv on joukko argumenttijonoja, jotka välitetään uudelle ohjelmalle. Sopimuksen mukaan ensimmäisen näistä merkkijonoista tulisi sisältää suoritettavaan tiedostoon liittyvä tiedostonimi.
- Se C vakio (vähintään C99 ja C11):
Jos argc-arvo on suurempi kuin nolla, merkkijono, johon argv viittaa [0 ] edustaa ohjelman nimeä; argv [0] [0] on tyhjä merkki, jos ohjelman nimeä ei ole saatavana isäntäympäristöstä.
Huomaa, että C-standardi sanoo ”ohjelma nimi ”ei” tiedostonimi ”.
Kommentit
- Ei ’ t tätä taukoa, jos saavut symlink toisesta symlinkistä?
- @Mehrdad, Kyllä, ’ on haittapuoli ja voi olla hämmentävää käyttäjälle.
- @rudimeier: ’ Miksi ’ -kohteet eivät ole oikeastaan syitä, ne ’ ovat vain ” homunculus ”, eli se vain herättää kysymyksen, miksi standardi vaatii tämän olevan asia.
- @ einpoklum OP ’ -kysymys oli: Miksi ohjelman nimi välitetään suoritettavalle tiedostolle? Vastasin: Koska POSIX- ja C-standardit käskevät meitä tekemään niin. Kuinka luulet, että ’ ei ole oikeastaan syy ? Jos lainaamiasi asiakirjoja, joita
olen lainannut, ei todennäköisesti olisi, monet ohjelmat eivät välittäisi ohjelman nimeä.
Vastaa
Sen lisäksi, että ohjelmat muuttavat heidän ohjelmiaan käyttäytyminen sen mukaan, miten heitä kutsuttiin, mielestäni argv[0]
on hyödyllinen ohjelman käytön tulostamisessa, kuten:
printf("Usage: %s [arguments]\n", argv[0]);
Tämän vuoksi käyttöviestissä käytetään aina nimeä, jolla sitä kutsuttiin. Jos ohjelma nimetään uudelleen, sen käyttöviesti muuttuu sen mukana. Se sisältää jopa polun nimen, jolla sitä kutsuttiin:
# cat foo.c #include <stdio.h> int main(int argc, char **argv) { printf("Usage: %s [arguments]\n", argv[0]); } # gcc -Wall -o foo foo.c # mv foo /usr/bin # cd /usr/bin # ln -s foo bar # foo Usage: foo [arguments] # bar Usage: bar [arguments] # ./foo Usage: ./foo [arguments] # /usr/bin/foo Usage: /usr/bin/foo [arguments]
Se on mukava kosketus, erityisesti pienille erikoistyökaluille / skripteille, jotka saattavat elää kaikkialla paikka.
Tämä näyttää olevan yleinen käytäntö myös GNU-työkaluissa, katso ls
esimerkiksi:
% ls --qq ls: unrecognized option "--qq" Try "ls --help" for more information. % /bin/ls --qq /bin/ls: unrecognized option "--qq" Try "/bin/ls --help" for more information.
kommentit
- +1. Aioin ehdottaa samaa. Kummallista, että niin monet ihmiset keskittyvät käyttäytymisen muuttamiseen eivätkä mainitse luultavasti ilmeisimpiä ja paljon laajempi käyttö.
Vastaus
Yksi suorittaa ohjelman kirjoittamisen: program_name0 arg1 arg2 arg3 ...
.
Joten kuoren pitäisi jo jakaa tunnus, ja ensimmäinen merkki on jo ohjelman nimi. Ja BTW, joten ohjelmapuolella ja kuoressa on samat indeksit.
Luulen, että tämä oli vain mukavuuden temppu (aivan alusta alkaen), ja kuten näette muissa vastauksissa, se oli myös erittäin kätevä, joten tätä perinnettä jatkettiin ja s et API: na.
Vastaus
Pohjimmiltaan argv sisältää ohjelman nimen, jotta voit kirjoittaa virheilmoituksia, kuten prgm: file: No such file or directory
, joka toteutetaan tällä tavoin:
fprintf( stderr, "%s: %s: No such file or directory\n", argv[0], argv[1] );
Vastaa
Toinen esimerkki tämän sovelluksesta on tämä ohjelma, joka korvaa itsensä … itsellä, kunnes kirjoitat jotain, joka ei ole ”t y
.
#include <unistd.h> #include <stdio.h> #include <stdlib.h> int main (int argc, char** argv) { (void) argc; printf("arg: %s\n", argv[1]); int count = atoi(argv[1]); if ( getchar() == "y" ) { ++count; char buf[20]; sprintf(buf, "%d", count); char* newargv[3]; newargv[0] = argv[0]; newargv[1] = buf; newargv[2] = NULL; execve(argv[0], newargv, NULL); } return count; }
On selvää, että keksitty, joskin mielenkiintoinen esimerkki, mutta mielestäni tällä voi olla todellisia käyttötarkoituksia – esimerkiksi itse päivittyvä binääri, joka kirjoittaa uudestaan oma muistitila ja uusi versio itsestä, jonka se ladasi tai muutti.
Esimerkki:
$ ./res 1 arg: 1 y arg: 2 y arg: 3 y arg: 4 y arg: 5 y arg: 6 y arg: 7 n 7 | $
Kommentit
- Onnittelut 1000: n saavuttamisesta.
vastaus
Ohjelman polku on argv[0]
, jotta ohjelma voi noutaa kokoonpanotiedostot jne. sen asennushakemistosta.
Tämä olisi mahdotonta ilman argv[0]
.
Kommentit
- Että ’ ei ole erityisen hyvä selitys – siellä ’ ei ole mitään syytä, miksi emme voineet ’ t eivät ole standardoineet esimerkiksi
(char *path_to_program, char **argv, int argc)
, esimerkiksi - Afaik, useimmat ohjelmat hakevat kokoonpanoa vakiopaikasta (
~/.<program>
,/etc/<program
,$XDG_CONFIG_HOME
) ja joko ota parametri muuttaaksesi sitä tai sinulla on käännösaika-vaihtoehto, joka leipoo vakiona binaariin.
vastaus
ccache käyttäytyy tällä tavalla jäljittelemään eri puhelut kääntäjän binääreille. ccache on kokoamisvälimuisti – koko kohta ei ole koskaan koota samaa lähdekoodia kahdesti, vaan palauttaa objektikoodi välimuistista, jos mahdollista.
Kohdasta ccache man page , ”ccache-tiedostoa voi käyttää kahdella tavalla. Voit joko etuliittää kokoamiskomennot ccachella tai antaa ccache-maskin kääntäjänä luomalla symbolisen linkin (nimeltä kääntäjä) ccache-välimuistiin. ensimmäinen menetelmä on kätevin, jos haluat vain kokeilla ccache-muistia tai haluat käyttää sitä joissakin tietyissä projekteissa. Toinen menetelmä on hyödyllisin silloin, kun haluat käyttää ccache-tiedostoa kaikissa kokoelmissasi. ”
symlinks-menetelmä sisältää näiden komentojen suorittamisen:
cp ccache /usr/local/bin/ ln -s ccache /usr/local/bin/gcc ln -s ccache /usr/local/bin/g++ ln -s ccache /usr/local/bin/cc ln -s ccache /usr/local/bin/c++ ... etc ...
… jonka seurauksena ccache sallii tarttua komentoihin, jotka muuten olisivat menneet kääntäjille, Näin ccache voi palauttaa välimuistitiedoston tai välittää komennon todelliselle kääntäjälle.
sh
on symlinkkidash
. He käyttäytyvät eri tavalla, kun niitä kutsutaan nimelläsh
tai nimellädash
busybox
(yleinen pelastuslevyillä ja vastaavilla), niin melkein kaikki (cp, mv, rm, ls, …) on symbolinen linkki väylälaatikkoon.gcc
,bash
,gunzip
, suurin osa muusta käyttöjärjestelmästä …), koska Linux on vain ydin.