gnu_parallel 240 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971
  1. #!/usr/bin/env perl
  2. # Copyright (C) 2007,2008,2009,2010,2011,2012,2013,2014 Ole Tange and
  3. # Free Software Foundation, Inc.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful, but
  11. # WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. # General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, see <http://www.gnu.org/licenses/>
  17. # or write to the Free Software Foundation, Inc., 51 Franklin St,
  18. # Fifth Floor, Boston, MA 02110-1301 USA
  19. # open3 used in Job::start
  20. use IPC::Open3;
  21. # &WNOHANG used in reaper
  22. use POSIX qw(:sys_wait_h setsid ceil :errno_h);
  23. # gensym used in Job::start
  24. use Symbol qw(gensym);
  25. # tempfile used in Job::start
  26. use File::Temp qw(tempfile tempdir);
  27. # mkpath used in openresultsfile
  28. use File::Path;
  29. # GetOptions used in get_options_from_array
  30. use Getopt::Long;
  31. # Used to ensure code quality
  32. use strict;
  33. use File::Basename;
  34. if(not $ENV{HOME}) {
  35. # $ENV{HOME} is sometimes not set if called from PHP
  36. ::warning("\$HOME not set. Using /tmp\n");
  37. $ENV{HOME} = "/tmp";
  38. }
  39. save_stdin_stdout_stderr();
  40. save_original_signal_handler();
  41. parse_options();
  42. ::debug("init", "Open file descriptors: ", join(" ",keys %Global::fd), "\n");
  43. my $number_of_args;
  44. if($Global::max_number_of_args) {
  45. $number_of_args=$Global::max_number_of_args;
  46. } elsif ($opt::X or $opt::m or $opt::xargs) {
  47. $number_of_args = undef;
  48. } else {
  49. $number_of_args = 1;
  50. }
  51. my @command;
  52. @command = @ARGV;
  53. my @fhlist;
  54. if($opt::pipepart) {
  55. @fhlist = map { open_or_exit($_) } "/dev/null";
  56. } else {
  57. @fhlist = map { open_or_exit($_) } @opt::a;
  58. if(not @fhlist and not $opt::pipe) {
  59. @fhlist = (*STDIN);
  60. }
  61. }
  62. if($opt::skip_first_line) {
  63. # Skip the first line for the first file handle
  64. my $fh = $fhlist[0];
  65. <$fh>;
  66. }
  67. if($opt::header and not $opt::pipe) {
  68. my $fh = $fhlist[0];
  69. # split with colsep or \t
  70. # $header force $colsep = \t if undef?
  71. my $delimiter = $opt::colsep;
  72. $delimiter ||= "\$";
  73. my $id = 1;
  74. for my $fh (@fhlist) {
  75. my $line = <$fh>;
  76. chomp($line);
  77. ::debug("init", "Delimiter: '$delimiter'");
  78. for my $s (split /$delimiter/o, $line) {
  79. ::debug("init", "Colname: '$s'");
  80. # Replace {colname} with {2}
  81. # TODO accept configurable short hands
  82. # TODO how to deal with headers in {=...=}
  83. for(@command) {
  84. s:\{$s(|/|//|\.|/\.)\}:\{$id$1\}:g;
  85. }
  86. $Global::input_source_header{$id} = $s;
  87. $id++;
  88. }
  89. }
  90. } else {
  91. my $id = 1;
  92. for my $fh (@fhlist) {
  93. $Global::input_source_header{$id} = $id;
  94. $id++;
  95. }
  96. }
  97. if($opt::filter_hosts and (@opt::sshlogin or @opt::sshloginfile)) {
  98. # Parallel check all hosts are up. Remove hosts that are down
  99. filter_hosts();
  100. }
  101. if($opt::nonall or $opt::onall) {
  102. onall(@command);
  103. wait_and_exit(min(undef_as_zero($Global::exitstatus),254));
  104. }
  105. # TODO --transfer foo/./bar --cleanup
  106. # multiple --transfer and --basefile with different /./
  107. $Global::JobQueue = JobQueue->new(
  108. \@command,\@fhlist,$Global::ContextReplace,$number_of_args,\@Global::ret_files);
  109. if($opt::eta or $opt::bar) {
  110. # Count the number of jobs before starting any
  111. $Global::JobQueue->total_jobs();
  112. }
  113. if($opt::pipepart) {
  114. @Global::cat_partials = map { pipe_part_files($_) } @opt::a;
  115. # Unget the command as many times as there are parts
  116. $Global::JobQueue->{'commandlinequeue'}->unget(
  117. map { $Global::JobQueue->{'commandlinequeue'}->get() } @Global::cat_partials
  118. );
  119. }
  120. for my $sshlogin (values %Global::host) {
  121. $sshlogin->max_jobs_running();
  122. }
  123. init_run_jobs();
  124. my $sem;
  125. if($Global::semaphore) {
  126. $sem = acquire_semaphore();
  127. }
  128. $SIG{TERM} = \&start_no_new_jobs;
  129. start_more_jobs();
  130. if(not $opt::pipepart) {
  131. if($opt::pipe) {
  132. spreadstdin();
  133. }
  134. }
  135. ::debug("init", "Start draining\n");
  136. drain_job_queue();
  137. ::debug("init", "Done draining\n");
  138. reaper();
  139. ::debug("init", "Done reaping\n");
  140. if($opt::pipe and @opt::a) {
  141. for my $job (@Global::tee_jobs) {
  142. unlink $job->fh(2,"name");
  143. $job->set_fh(2,"name","");
  144. $job->print();
  145. unlink $job->fh(1,"name");
  146. }
  147. }
  148. ::debug("init", "Cleaning\n");
  149. cleanup();
  150. if($Global::semaphore) {
  151. $sem->release();
  152. }
  153. for(keys %Global::sshmaster) {
  154. kill "TERM", $_;
  155. }
  156. ::debug("init", "Halt\n");
  157. if($opt::halt_on_error) {
  158. wait_and_exit($Global::halt_on_error_exitstatus);
  159. } else {
  160. wait_and_exit(min(undef_as_zero($Global::exitstatus),254));
  161. }
  162. sub __PIPE_MODE__ {}
  163. sub pipe_part_files {
  164. # Input:
  165. # $file = the file to read
  166. # Returns:
  167. # @commands that will cat_partial each part
  168. my ($file) = @_;
  169. my $buf = "";
  170. my $header = find_header(\$buf,open_or_exit($file));
  171. # find positions
  172. my @pos = find_split_positions($file,$opt::blocksize,length $header);
  173. # Make @cat_partials
  174. my @cat_partials = ();
  175. for(my $i=0; $i<$#pos; $i++) {
  176. push @cat_partials, cat_partial($file, 0, length($header), $pos[$i], $pos[$i+1]);
  177. }
  178. # Remote exec should look like:
  179. # ssh -oLogLevel=quiet lo 'eval `echo $SHELL | grep "/t\{0,1\}csh" > /dev/null && echo setenv PARALLEL_SEQ '$PARALLEL_SEQ'\; setenv PARALLEL_PID '$PARALLEL_PID' || echo PARALLEL_SEQ='$PARALLEL_SEQ'\;export PARALLEL_SEQ\; PARALLEL_PID='$PARALLEL_PID'\;export PARALLEL_PID` ;' tty\ \>/dev/null\ \&\&\ stty\ isig\ -onlcr\ -echo\;echo\ \$SHELL\ \|\ grep\ \"/t\\\{0,1\\\}csh\"\ \>\ /dev/null\ \&\&\ setenv\ FOO\ /tmp/foo\ \|\|\ export\ FOO=/tmp/foo\; \(wc\ -\ \$FOO\)
  180. # ssh -tt not allowed. Remote will die due to broken pipe anyway.
  181. # TODO test remote with --fifo / --cat
  182. return @cat_partials;
  183. }
  184. sub find_header {
  185. # Input:
  186. # $buf_ref = reference to read-in buffer
  187. # $fh = filehandle to read from
  188. # Uses:
  189. # $opt::header
  190. # $opt::blocksize
  191. # Returns:
  192. # $header string
  193. my ($buf_ref, $fh) = @_;
  194. my $header = "";
  195. if($opt::header) {
  196. if($opt::header eq ":") { $opt::header = "(.*\n)"; }
  197. # Number = number of lines
  198. $opt::header =~ s/^(\d+)$/"(.*\n)"x$1/e;
  199. while(read($fh,substr($$buf_ref,length $$buf_ref,0),$opt::blocksize)) {
  200. if($$buf_ref=~s/^($opt::header)//) {
  201. $header = $1;
  202. last;
  203. }
  204. }
  205. }
  206. return $header;
  207. }
  208. sub find_split_positions {
  209. # Input:
  210. # $file = the file to read
  211. # $block = (minimal) --block-size of each chunk
  212. # $headerlen = length of header to be skipped
  213. # Uses:
  214. # $opt::recstart
  215. # $opt::recend
  216. # Returns:
  217. # @positions of block start/end
  218. my($file, $block, $headerlen) = @_;
  219. my $size = -s $file;
  220. $block = int $block;
  221. # The optimal dd blocksize for mint, redhat, solaris, openbsd = 2^17..2^20
  222. # The optimal dd blocksize for freebsd = 2^15..2^17
  223. my $dd_block_size = 131072; # 2^17
  224. my @pos;
  225. my ($recstart,$recend) = recstartrecend();
  226. my $recendrecstart = $recend.$recstart;
  227. my $fh = ::open_or_exit($file);
  228. push(@pos,$headerlen);
  229. for(my $pos = $block+$headerlen; $pos < $size; $pos += $block) {
  230. my $buf;
  231. seek($fh, $pos, 0) || die;
  232. while(read($fh,substr($buf,length $buf,0),$dd_block_size)) {
  233. if($opt::regexp) {
  234. # If match /$recend$recstart/ => Record position
  235. if($buf =~ /(.*$recend)$recstart/os) {
  236. my $i = length($1);
  237. push(@pos,$pos+$i);
  238. # Start looking for next record _after_ this match
  239. $pos += $i;
  240. last;
  241. }
  242. } else {
  243. # If match $recend$recstart => Record position
  244. my $i = index($buf,$recendrecstart);
  245. if($i != -1) {
  246. push(@pos,$pos+$i);
  247. # Start looking for next record _after_ this match
  248. $pos += $i;
  249. last;
  250. }
  251. }
  252. }
  253. }
  254. push(@pos,$size);
  255. close $fh;
  256. return @pos;
  257. }
  258. sub cat_partial {
  259. # Input:
  260. # $file = the file to read
  261. # ($start, $end, [$start2, $end2, ...]) = start byte, end byte
  262. # Returns:
  263. # Efficient perl command to copy $start..$end, $start2..$end2, ... to stdout
  264. my($file, @start_end) = @_;
  265. my($start, $i);
  266. # Convert start_end to start_len
  267. my @start_len = map { if(++$i % 2) { $start = $_; } else { $_-$start } } @start_end;
  268. return "<". shell_quote_scalar($file) .
  269. q{ perl -e 'while(@ARGV) { sysseek(STDIN,shift,0) || die; $left = shift; while($read = sysread(STDIN,$buf, ($left > 32768 ? 32768 : $left))){ $left -= $read; syswrite(STDOUT,$buf); } }' } .
  270. " @start_len";
  271. }
  272. sub spreadstdin {
  273. # read a record
  274. # Spawn a job and print the record to it.
  275. # Uses:
  276. # $opt::blocksize
  277. # STDIN
  278. # $opr::r
  279. # $Global::max_lines
  280. # $Global::max_number_of_args
  281. # $opt::regexp
  282. # $Global::start_no_new_jobs
  283. # $opt::roundrobin
  284. # %Global::running
  285. my $buf = "";
  286. my ($recstart,$recend) = recstartrecend();
  287. my $recendrecstart = $recend.$recstart;
  288. my $chunk_number = 1;
  289. my $one_time_through;
  290. my $blocksize = $opt::blocksize;
  291. my $in = *STDIN;
  292. my $header = find_header(\$buf,$in);
  293. while(1) {
  294. my $anything_written = 0;
  295. if(not read($in,substr($buf,length $buf,0),$blocksize)) {
  296. # End-of-file
  297. $chunk_number != 1 and last;
  298. # Force the while-loop once if everything was read by header reading
  299. $one_time_through++ and last;
  300. }
  301. if($opt::r) {
  302. # Remove empty lines
  303. $buf =~ s/^\s*\n//gm;
  304. if(length $buf == 0) {
  305. next;
  306. }
  307. }
  308. if($Global::max_lines and not $Global::max_number_of_args) {
  309. # Read n-line records
  310. my $n_lines = $buf =~ tr/\n/\n/;
  311. my $last_newline_pos = rindex($buf,"\n");
  312. while($n_lines % $Global::max_lines) {
  313. $n_lines--;
  314. $last_newline_pos = rindex($buf,"\n",$last_newline_pos-1);
  315. }
  316. # Chop at $last_newline_pos as that is where n-line record ends
  317. $anything_written +=
  318. write_record_to_pipe($chunk_number++,\$header,\$buf,
  319. $recstart,$recend,$last_newline_pos+1);
  320. substr($buf,0,$last_newline_pos+1) = "";
  321. } elsif($opt::regexp) {
  322. if($Global::max_number_of_args) {
  323. # -N => (start..*?end){n}
  324. # -L -N => (start..*?end){n*l}
  325. my $read_n_lines = $Global::max_number_of_args * ($Global::max_lines || 1);
  326. while($buf =~ s/((?:$recstart.*?$recend){$read_n_lines})($recstart.*)$/$2/os) {
  327. # Copy to modifiable variable
  328. my $b = $1;
  329. $anything_written +=
  330. write_record_to_pipe($chunk_number++,\$header,\$b,
  331. $recstart,$recend,length $1);
  332. }
  333. } else {
  334. # Find the last recend-recstart in $buf
  335. if($buf =~ s/(.*$recend)($recstart.*?)$/$2/os) {
  336. # Copy to modifiable variable
  337. my $b = $1;
  338. $anything_written +=
  339. write_record_to_pipe($chunk_number++,\$header,\$b,
  340. $recstart,$recend,length $1);
  341. }
  342. }
  343. } else {
  344. if($Global::max_number_of_args) {
  345. # -N => (start..*?end){n}
  346. my $i = 0;
  347. my $read_n_lines = $Global::max_number_of_args * ($Global::max_lines || 1);
  348. while(($i = nindex(\$buf,$recendrecstart,$read_n_lines)) != -1) {
  349. $i += length $recend; # find the actual splitting location
  350. $anything_written +=
  351. write_record_to_pipe($chunk_number++,\$header,\$buf,
  352. $recstart,$recend,$i);
  353. substr($buf,0,$i) = "";
  354. }
  355. } else {
  356. # Find the last recend-recstart in $buf
  357. my $i = rindex($buf,$recendrecstart);
  358. if($i != -1) {
  359. $i += length $recend; # find the actual splitting location
  360. $anything_written +=
  361. write_record_to_pipe($chunk_number++,\$header,\$buf,
  362. $recstart,$recend,$i);
  363. substr($buf,0,$i) = "";
  364. }
  365. }
  366. }
  367. if(not $anything_written and not eof($in)) {
  368. # Nothing was written - maybe the block size < record size?
  369. # Increase blocksize exponentially
  370. my $old_blocksize = $blocksize;
  371. $blocksize = ceil($blocksize * 1.3 + 1);
  372. ::warning("A record was longer than $old_blocksize. " .
  373. "Increasing to --blocksize $blocksize\n");
  374. }
  375. }
  376. ::debug("init", "Done reading input\n");
  377. # If there is anything left in the buffer write it
  378. substr($buf,0,0) = "";
  379. write_record_to_pipe($chunk_number++,\$header,\$buf,$recstart,$recend,length $buf);
  380. $Global::start_no_new_jobs ||= 1;
  381. if($opt::roundrobin) {
  382. for my $job (values %Global::running) {
  383. close $job->fh(0,"w");
  384. }
  385. my %incomplete_jobs = %Global::running;
  386. my $sleep = 1;
  387. while(keys %incomplete_jobs) {
  388. my $something_written = 0;
  389. for my $pid (keys %incomplete_jobs) {
  390. my $job = $incomplete_jobs{$pid};
  391. if($job->stdin_buffer_length()) {
  392. $something_written += $job->non_block_write();
  393. } else {
  394. delete $incomplete_jobs{$pid}
  395. }
  396. }
  397. if($something_written) {
  398. $sleep = $sleep/2+0.001;
  399. }
  400. $sleep = ::reap_usleep($sleep);
  401. }
  402. }
  403. }
  404. sub recstartrecend {
  405. # Uses:
  406. # $opt::recstart
  407. # $opt::recend
  408. # Returns:
  409. # $recstart,$recend with default values and regexp conversion
  410. my($recstart,$recend);
  411. if(defined($opt::recstart) and defined($opt::recend)) {
  412. # If both --recstart and --recend is given then both must match
  413. $recstart = $opt::recstart;
  414. $recend = $opt::recend;
  415. } elsif(defined($opt::recstart)) {
  416. # If --recstart is given it must match start of record
  417. $recstart = $opt::recstart;
  418. $recend = "";
  419. } elsif(defined($opt::recend)) {
  420. # If --recend is given then it must match end of record
  421. $recstart = "";
  422. $recend = $opt::recend;
  423. }
  424. if($opt::regexp) {
  425. # If $recstart/$recend contains '|' this should only apply to the regexp
  426. $recstart = "(?:".$recstart.")";
  427. $recend = "(?:".$recend.")";
  428. } else {
  429. # $recstart/$recend = printf strings (\n)
  430. $recstart =~ s/\\([0rnt\'\"\\])/"qq|\\$1|"/gee;
  431. $recend =~ s/\\([0rnt\'\"\\])/"qq|\\$1|"/gee;
  432. }
  433. return ($recstart,$recend);
  434. }
  435. sub nindex {
  436. # See if string is in buffer N times
  437. # Returns:
  438. # the position where the Nth copy is found
  439. my ($buf_ref, $str, $n) = @_;
  440. my $i = 0;
  441. for(1..$n) {
  442. $i = index($$buf_ref,$str,$i+1);
  443. if($i == -1) { last }
  444. }
  445. return $i;
  446. }
  447. {
  448. my @robin_queue;
  449. sub round_robin_write {
  450. # Input:
  451. # $header_ref = ref to $header string
  452. # $block_ref = ref to $block to be written
  453. # $recstart = record start string
  454. # $recend = record end string
  455. # $endpos = end position of $block
  456. # Uses:
  457. # %Global::running
  458. my ($header_ref,$block_ref,$recstart,$recend,$endpos) = @_;
  459. my $something_written = 0;
  460. my $block_passed = 0;
  461. my $sleep = 1;
  462. while(not $block_passed) {
  463. # Continue flushing existing buffers
  464. # until one is empty and a new block is passed
  465. # Make a queue to spread the blocks evenly
  466. if(not @robin_queue) {
  467. push @robin_queue, values %Global::running;
  468. }
  469. while(my $job = shift @robin_queue) {
  470. if($job->stdin_buffer_length() > 0) {
  471. $something_written += $job->non_block_write();
  472. } else {
  473. $job->set_stdin_buffer($header_ref,$block_ref,$endpos,$recstart,$recend);
  474. $block_passed = 1;
  475. $job->set_virgin(0);
  476. $something_written += $job->non_block_write();
  477. last;
  478. }
  479. }
  480. $sleep = ::reap_usleep($sleep);
  481. }
  482. return $something_written;
  483. }
  484. }
  485. sub write_record_to_pipe {
  486. # Fork then
  487. # Write record from pos 0 .. $endpos to pipe
  488. # Input:
  489. # $chunk_number = sequence number - to see if already run
  490. # $header_ref = reference to header string to prepend
  491. # $record_ref = reference to record to write
  492. # $recstart = start string of record
  493. # $recend = end string of record
  494. # $endpos = position in $record_ref where record ends
  495. # Uses:
  496. # $Global::job_already_run
  497. # $opt::roundrobin
  498. # @Global::virgin_jobs
  499. # Returns:
  500. # Number of chunks written (0 or 1)
  501. my ($chunk_number,$header_ref,$record_ref,$recstart,$recend,$endpos) = @_;
  502. if($endpos == 0) { return 0; }
  503. if(vec($Global::job_already_run,$chunk_number,1)) { return 1; }
  504. if($opt::roundrobin) {
  505. return round_robin_write($header_ref,$record_ref,$recstart,$recend,$endpos);
  506. }
  507. # If no virgin found, backoff
  508. my $sleep = 0.0001; # 0.01 ms - better performance on highend
  509. while(not @Global::virgin_jobs) {
  510. ::debug("pipe", "No virgin jobs");
  511. $sleep = ::reap_usleep($sleep);
  512. # Jobs may not be started because of loadavg
  513. # or too little time between each ssh login.
  514. start_more_jobs();
  515. }
  516. my $job = shift @Global::virgin_jobs;
  517. # Job is no longer virgin
  518. $job->set_virgin(0);
  519. if(fork()) {
  520. # Skip
  521. } else {
  522. # Chop of at $endpos as we do not know how many rec_sep will
  523. # be removed.
  524. substr($$record_ref,$endpos,length $$record_ref) = "";
  525. # Remove rec_sep
  526. if($opt::remove_rec_sep) {
  527. Job::remove_rec_sep($record_ref,$recstart,$recend);
  528. }
  529. $job->write($header_ref);
  530. $job->write($record_ref);
  531. close $job->fh(0,"w");
  532. exit(0);
  533. }
  534. close $job->fh(0,"w");
  535. return 1;
  536. }
  537. sub __SEM_MODE__ {}
  538. sub acquire_semaphore {
  539. # Acquires semaphore. If needed: spawns to the background
  540. # Uses:
  541. # @Global::host
  542. # Returns:
  543. # The semaphore to be released when jobs is complete
  544. $Global::host{':'} = SSHLogin->new(":");
  545. my $sem = Semaphore->new($Semaphore::name,$Global::host{':'}->max_jobs_running());
  546. $sem->acquire();
  547. if($Semaphore::fg) {
  548. # skip
  549. } else {
  550. # If run in the background, the PID will change
  551. # therefore release and re-acquire the semaphore
  552. $sem->release();
  553. if(fork()) {
  554. exit(0);
  555. } else {
  556. # child
  557. # Get a semaphore for this pid
  558. ::die_bug("Can't start a new session: $!") if setsid() == -1;
  559. $sem = Semaphore->new($Semaphore::name,$Global::host{':'}->max_jobs_running());
  560. $sem->acquire();
  561. }
  562. }
  563. return $sem;
  564. }
  565. sub __PARSE_OPTIONS__ {}
  566. sub options_hash {
  567. # Returns:
  568. # %hash = the GetOptions config
  569. return
  570. ("debug|D=s" => \$opt::D,
  571. "xargs" => \$opt::xargs,
  572. "m" => \$opt::m,
  573. "X" => \$opt::X,
  574. "v" => \@opt::v,
  575. "joblog=s" => \$opt::joblog,
  576. "results|result|res=s" => \$opt::results,
  577. "resume" => \$opt::resume,
  578. "resume-failed|resumefailed" => \$opt::resume_failed,
  579. "silent" => \$opt::silent,
  580. #"silent-error|silenterror" => \$opt::silent_error,
  581. "keep-order|keeporder|k" => \$opt::keeporder,
  582. "group" => \$opt::group,
  583. "g" => \$opt::retired,
  584. "ungroup|u" => \$opt::ungroup,
  585. "linebuffer|linebuffered|line-buffer|line-buffered" => \$opt::linebuffer,
  586. "tmux" => \$opt::tmux,
  587. "null|0" => \$opt::0,
  588. "quote|q" => \$opt::q,
  589. # Replacement strings
  590. "parens=s" => \$opt::parens,
  591. "rpl=s" => \@opt::rpl,
  592. "plus" => \$opt::plus,
  593. "I=s" => \$opt::I,
  594. "extensionreplace|er=s" => \$opt::U,
  595. "U=s" => \$opt::retired,
  596. "basenamereplace|bnr=s" => \$opt::basenamereplace,
  597. "dirnamereplace|dnr=s" => \$opt::dirnamereplace,
  598. "basenameextensionreplace|bner=s" => \$opt::basenameextensionreplace,
  599. "seqreplace=s" => \$opt::seqreplace,
  600. "slotreplace=s" => \$opt::slotreplace,
  601. "jobs|j=s" => \$opt::jobs,
  602. "delay=f" => \$opt::delay,
  603. "sshdelay=f" => \$opt::sshdelay,
  604. "load=s" => \$opt::load,
  605. "noswap" => \$opt::noswap,
  606. "max-line-length-allowed" => \$opt::max_line_length_allowed,
  607. "number-of-cpus" => \$opt::number_of_cpus,
  608. "number-of-cores" => \$opt::number_of_cores,
  609. "use-cpus-instead-of-cores" => \$opt::use_cpus_instead_of_cores,
  610. "shellquote|shell_quote|shell-quote" => \$opt::shellquote,
  611. "nice=i" => \$opt::nice,
  612. "timeout=s" => \$opt::timeout,
  613. "tag" => \$opt::tag,
  614. "tagstring|tag-string=s" => \$opt::tagstring,
  615. "onall" => \$opt::onall,
  616. "nonall" => \$opt::nonall,
  617. "filter-hosts|filterhosts|filter-host" => \$opt::filter_hosts,
  618. "sshlogin|S=s" => \@opt::sshlogin,
  619. "sshloginfile|slf=s" => \@opt::sshloginfile,
  620. "controlmaster|M" => \$opt::controlmaster,
  621. "return=s" => \@opt::return,
  622. "trc=s" => \@opt::trc,
  623. "transfer" => \$opt::transfer,
  624. "cleanup" => \$opt::cleanup,
  625. "basefile|bf=s" => \@opt::basefile,
  626. "B=s" => \$opt::retired,
  627. "ctrlc|ctrl-c" => \$opt::ctrlc,
  628. "noctrlc|no-ctrlc|no-ctrl-c" => \$opt::noctrlc,
  629. "workdir|work-dir|wd=s" => \$opt::workdir,
  630. "W=s" => \$opt::retired,
  631. "tmpdir=s" => \$opt::tmpdir,
  632. "tempdir=s" => \$opt::tmpdir,
  633. "use-compress-program|compress-program=s" => \$opt::compress_program,
  634. "use-decompress-program|decompress-program=s" => \$opt::decompress_program,
  635. "compress" => \$opt::compress,
  636. "tty" => \$opt::tty,
  637. "T" => \$opt::retired,
  638. "halt-on-error|halt=s" => \$opt::halt_on_error,
  639. "H=i" => \$opt::retired,
  640. "retries=i" => \$opt::retries,
  641. "dry-run|dryrun" => \$opt::dryrun,
  642. "progress" => \$opt::progress,
  643. "eta" => \$opt::eta,
  644. "bar" => \$opt::bar,
  645. "arg-sep|argsep=s" => \$opt::arg_sep,
  646. "arg-file-sep|argfilesep=s" => \$opt::arg_file_sep,
  647. "trim=s" => \$opt::trim,
  648. "env=s" => \@opt::env,
  649. "recordenv|record-env" => \$opt::record_env,
  650. "plain" => \$opt::plain,
  651. "profile|J=s" => \@opt::profile,
  652. "pipe|spreadstdin" => \$opt::pipe,
  653. "robin|round-robin|roundrobin" => \$opt::roundrobin,
  654. "recstart=s" => \$opt::recstart,
  655. "recend=s" => \$opt::recend,
  656. "regexp|regex" => \$opt::regexp,
  657. "remove-rec-sep|removerecsep|rrs" => \$opt::remove_rec_sep,
  658. "files|output-as-files|outputasfiles" => \$opt::files,
  659. "block|block-size|blocksize=s" => \$opt::blocksize,
  660. "tollef" => \$opt::retired,
  661. "gnu" => \$opt::gnu,
  662. "xapply" => \$opt::xapply,
  663. "bibtex" => \$opt::bibtex,
  664. "nn|nonotice|no-notice" => \$opt::no_notice,
  665. # xargs-compatibility - implemented, man, testsuite
  666. "max-procs|P=s" => \$opt::jobs,
  667. "delimiter|d=s" => \$opt::d,
  668. "max-chars|s=i" => \$opt::max_chars,
  669. "arg-file|a=s" => \@opt::a,
  670. "no-run-if-empty|r" => \$opt::r,
  671. "replace|i:s" => \$opt::i,
  672. "E=s" => \$opt::eof,
  673. "eof|e:s" => \$opt::eof,
  674. "max-args|n=i" => \$opt::max_args,
  675. "max-replace-args|N=i" => \$opt::max_replace_args,
  676. "colsep|col-sep|C=s" => \$opt::colsep,
  677. "help|h" => \$opt::help,
  678. "L=f" => \$opt::L,
  679. "max-lines|l:f" => \$opt::max_lines,
  680. "interactive|p" => \$opt::p,
  681. "verbose|t" => \$opt::verbose,
  682. "version|V" => \$opt::version,
  683. "minversion|min-version=i" => \$opt::minversion,
  684. "show-limits|showlimits" => \$opt::show_limits,
  685. "exit|x" => \$opt::x,
  686. # Semaphore
  687. "semaphore" => \$opt::semaphore,
  688. "semaphoretimeout=i" => \$opt::semaphoretimeout,
  689. "semaphorename|id=s" => \$opt::semaphorename,
  690. "fg" => \$opt::fg,
  691. "bg" => \$opt::bg,
  692. "wait" => \$opt::wait,
  693. # Shebang #!/usr/bin/parallel --shebang
  694. "shebang|hashbang" => \$opt::shebang,
  695. "internal-pipe-means-argfiles" => \$opt::internal_pipe_means_argfiles,
  696. "Y" => \$opt::retired,
  697. "skip-first-line" => \$opt::skip_first_line,
  698. "header=s" => \$opt::header,
  699. "cat" => \$opt::cat,
  700. "fifo" => \$opt::fifo,
  701. "pipepart|pipe-part" => \$opt::pipepart,
  702. "hgrp|hostgroup|hostgroups" => \$opt::hostgroups,
  703. );
  704. }
  705. sub get_options_from_array {
  706. # Run GetOptions on @array
  707. # Input:
  708. # $array_ref = ref to @ARGV to parse
  709. # @keep_only = Keep only these options
  710. # Uses:
  711. # @ARGV
  712. # Returns:
  713. # true if parsing worked
  714. # false if parsing failed
  715. # @$array_ref is changed
  716. my ($array_ref, @keep_only) = @_;
  717. if(not @$array_ref) {
  718. # Empty array: No need to look more at that
  719. return 1;
  720. }
  721. # A bit of shuffling of @ARGV needed as GetOptionsFromArray is not
  722. # supported everywhere
  723. my @save_argv;
  724. my $this_is_ARGV = (\@::ARGV == $array_ref);
  725. if(not $this_is_ARGV) {
  726. @save_argv = @::ARGV;
  727. @::ARGV = @{$array_ref};
  728. }
  729. # If @keep_only set: Ignore all values except @keep_only
  730. my %options = options_hash();
  731. if(@keep_only) {
  732. my (%keep,@dummy);
  733. @keep{@keep_only} = @keep_only;
  734. for my $k (grep { not $keep{$_} } keys %options) {
  735. # Store the value of the option in @dummy
  736. $options{$k} = \@dummy;
  737. }
  738. }
  739. my $retval = GetOptions(%options);
  740. if(not $this_is_ARGV) {
  741. @{$array_ref} = @::ARGV;
  742. @::ARGV = @save_argv;
  743. }
  744. return $retval;
  745. }
  746. sub parse_options {
  747. # Returns: N/A
  748. # Defaults:
  749. $Global::version = 20141122;
  750. $Global::progname = 'parallel';
  751. $Global::infinity = 2**31;
  752. $Global::debug = 0;
  753. $Global::verbose = 0;
  754. $Global::quoting = 0;
  755. # Read only table with default --rpl values
  756. %Global::replace =
  757. (
  758. '{}' => '',
  759. '{#}' => '1 $_=$job->seq()',
  760. '{%}' => '1 $_=$job->slot()',
  761. '{/}' => 's:.*/::',
  762. '{//}' => '$Global::use{"File::Basename"} ||= eval "use File::Basename; 1;"; $_ = dirname($_);',
  763. '{/.}' => 's:.*/::; s:\.[^/.]+$::;',
  764. '{.}' => 's:\.[^/.]+$::',
  765. );
  766. %Global::plus =
  767. (
  768. # {} = {+/}/{/}
  769. # = {.}.{+.} = {+/}/{/.}.{+.}
  770. # = {..}.{+..} = {+/}/{/..}.{+..}
  771. # = {...}.{+...} = {+/}/{/...}.{+...}
  772. '{+/}' => 's:/[^/]*$::',
  773. '{+.}' => 's:.*\.::',
  774. '{+..}' => 's:.*\.([^.]*\.):$1:',
  775. '{+...}' => 's:.*\.([^.]*\.[^.]*\.):$1:',
  776. '{..}' => 's:\.[^/.]+$::; s:\.[^/.]+$::',
  777. '{...}' => 's:\.[^/.]+$::; s:\.[^/.]+$::; s:\.[^/.]+$::',
  778. '{/..}' => 's:.*/::; s:\.[^/.]+$::; s:\.[^/.]+$::',
  779. '{/...}' => 's:.*/::; s:\.[^/.]+$::; s:\.[^/.]+$::; s:\.[^/.]+$::',
  780. );
  781. # Modifiable copy of %Global::replace
  782. %Global::rpl = %Global::replace;
  783. $Global::parens = "{==}";
  784. $/="\n";
  785. $Global::ignore_empty = 0;
  786. $Global::interactive = 0;
  787. $Global::stderr_verbose = 0;
  788. $Global::default_simultaneous_sshlogins = 9;
  789. $Global::exitstatus = 0;
  790. $Global::halt_on_error_exitstatus = 0;
  791. $Global::arg_sep = ":::";
  792. $Global::arg_file_sep = "::::";
  793. $Global::trim = 'n';
  794. $Global::max_jobs_running = 0;
  795. $Global::job_already_run = '';
  796. $ENV{'TMPDIR'} ||= "/tmp";
  797. @ARGV=read_options();
  798. if(@opt::v) { $Global::verbose = $#opt::v+1; } # Convert -v -v to v=2
  799. $Global::debug = $opt::D;
  800. $Global::shell = $ENV{'PARALLEL_SHELL'} || parent_shell($$) || $ENV{'SHELL'} || "/bin/sh";
  801. if(defined $opt::X) { $Global::ContextReplace = 1; }
  802. if(defined $opt::silent) { $Global::verbose = 0; }
  803. if(defined $opt::0) { $/ = "\0"; }
  804. if(defined $opt::d) { my $e="sprintf \"$opt::d\""; $/ = eval $e; }
  805. if(defined $opt::p) { $Global::interactive = $opt::p; }
  806. if(defined $opt::q) { $Global::quoting = 1; }
  807. if(defined $opt::r) { $Global::ignore_empty = 1; }
  808. if(defined $opt::verbose) { $Global::stderr_verbose = 1; }
  809. # Deal with --rpl
  810. sub rpl {
  811. # Modify %Global::rpl
  812. # Replace $old with $new
  813. my ($old,$new) = @_;
  814. if($old ne $new) {
  815. $Global::rpl{$new} = $Global::rpl{$old};
  816. delete $Global::rpl{$old};
  817. }
  818. }
  819. if(defined $opt::parens) { $Global::parens = $opt::parens; }
  820. my $parenslen = 0.5*length $Global::parens;
  821. $Global::parensleft = substr($Global::parens,0,$parenslen);
  822. $Global::parensright = substr($Global::parens,$parenslen);
  823. if(defined $opt::plus) { %Global::rpl = (%Global::plus,%Global::rpl); }
  824. if(defined $opt::I) { rpl('{}',$opt::I); }
  825. if(defined $opt::U) { rpl('{.}',$opt::U); }
  826. if(defined $opt::i and $opt::i) { rpl('{}',$opt::i); }
  827. if(defined $opt::basenamereplace) { rpl('{/}',$opt::basenamereplace); }
  828. if(defined $opt::dirnamereplace) { rpl('{//}',$opt::dirnamereplace); }
  829. if(defined $opt::seqreplace) { rpl('{#}',$opt::seqreplace); }
  830. if(defined $opt::slotreplace) { rpl('{%}',$opt::slotreplace); }
  831. if(defined $opt::basenameextensionreplace) {
  832. rpl('{/.}',$opt::basenameextensionreplace);
  833. }
  834. for(@opt::rpl) {
  835. # Create $Global::rpl entries for --rpl options
  836. # E.g: "{..} s:\.[^.]+$:;s:\.[^.]+$:;"
  837. my ($shorthand,$long) = split/ /,$_,2;
  838. $Global::rpl{$shorthand} = $long;
  839. }
  840. if(defined $opt::eof) { $Global::end_of_file_string = $opt::eof; }
  841. if(defined $opt::max_args) { $Global::max_number_of_args = $opt::max_args; }
  842. if(defined $opt::timeout) { $Global::timeoutq = TimeoutQueue->new($opt::timeout); }
  843. if(defined $opt::tmpdir) { $ENV{'TMPDIR'} = $opt::tmpdir; }
  844. if(defined $opt::help) { die_usage(); }
  845. if(defined $opt::colsep) { $Global::trim = 'lr'; }
  846. if(defined $opt::header) { $opt::colsep = defined $opt::colsep ? $opt::colsep : "\t"; }
  847. if(defined $opt::trim) { $Global::trim = $opt::trim; }
  848. if(defined $opt::arg_sep) { $Global::arg_sep = $opt::arg_sep; }
  849. if(defined $opt::arg_file_sep) { $Global::arg_file_sep = $opt::arg_file_sep; }
  850. if(defined $opt::number_of_cpus) { print SSHLogin::no_of_cpus(),"\n"; wait_and_exit(0); }
  851. if(defined $opt::number_of_cores) {
  852. print SSHLogin::no_of_cores(),"\n"; wait_and_exit(0);
  853. }
  854. if(defined $opt::max_line_length_allowed) {
  855. print Limits::Command::real_max_length(),"\n"; wait_and_exit(0);
  856. }
  857. if(defined $opt::version) { version(); wait_and_exit(0); }
  858. if(defined $opt::bibtex) { bibtex(); wait_and_exit(0); }
  859. if(defined $opt::record_env) { record_env(); wait_and_exit(0); }
  860. if(defined $opt::show_limits) { show_limits(); }
  861. if(@opt::sshlogin) { @Global::sshlogin = @opt::sshlogin; }
  862. if(@opt::sshloginfile) { read_sshloginfiles(@opt::sshloginfile); }
  863. if(@opt::return) { push @Global::ret_files, @opt::return; }
  864. if(not defined $opt::recstart and
  865. not defined $opt::recend) { $opt::recend = "\n"; }
  866. if(not defined $opt::blocksize) { $opt::blocksize = "1M"; }
  867. $opt::blocksize = multiply_binary_prefix($opt::blocksize);
  868. if(defined $opt::controlmaster) { $opt::noctrlc = 1; }
  869. if(defined $opt::semaphore) { $Global::semaphore = 1; }
  870. if(defined $opt::semaphoretimeout) { $Global::semaphore = 1; }
  871. if(defined $opt::semaphorename) { $Global::semaphore = 1; }
  872. if(defined $opt::fg) { $Global::semaphore = 1; }
  873. if(defined $opt::bg) { $Global::semaphore = 1; }
  874. if(defined $opt::wait) { $Global::semaphore = 1; }
  875. if(defined $opt::halt_on_error and
  876. $opt::halt_on_error=~/%/) { $opt::halt_on_error /= 100; }
  877. if(defined $opt::timeout and $opt::timeout !~ /^\d+(\.\d+)?%?$/) {
  878. ::error("--timeout must be seconds or percentage\n");
  879. wait_and_exit(255);
  880. }
  881. if(defined $opt::minversion) {
  882. print $Global::version,"\n";
  883. if($Global::version < $opt::minversion) {
  884. wait_and_exit(255);
  885. } else {
  886. wait_and_exit(0);
  887. }
  888. }
  889. if(not defined $opt::delay) {
  890. # Set --delay to --sshdelay if not set
  891. $opt::delay = $opt::sshdelay;
  892. }
  893. if($opt::compress_program) {
  894. $opt::compress = 1;
  895. $opt::decompress_program ||= $opt::compress_program." -dc";
  896. }
  897. if($opt::compress) {
  898. my ($compress, $decompress) = find_compression_program();
  899. $opt::compress_program ||= $compress;
  900. $opt::decompress_program ||= $decompress;
  901. }
  902. if(defined $opt::nonall) {
  903. # Append a dummy empty argument
  904. push @ARGV, $Global::arg_sep, "";
  905. }
  906. if(defined $opt::tty) {
  907. # Defaults for --tty: -j1 -u
  908. # Can be overridden with -jXXX -g
  909. if(not defined $opt::jobs) {
  910. $opt::jobs = 1;
  911. }
  912. if(not defined $opt::group) {
  913. $opt::ungroup = 0;
  914. }
  915. }
  916. if(@opt::trc) {
  917. push @Global::ret_files, @opt::trc;
  918. $opt::transfer = 1;
  919. $opt::cleanup = 1;
  920. }
  921. if(defined $opt::max_lines) {
  922. if($opt::max_lines eq "-0") {
  923. # -l -0 (swallowed -0)
  924. $opt::max_lines = 1;
  925. $opt::0 = 1;
  926. $/ = "\0";
  927. } elsif ($opt::max_lines == 0) {
  928. # If not given (or if 0 is given) => 1
  929. $opt::max_lines = 1;
  930. }
  931. $Global::max_lines = $opt::max_lines;
  932. if(not $opt::pipe) {
  933. # --pipe -L means length of record - not max_number_of_args
  934. $Global::max_number_of_args ||= $Global::max_lines;
  935. }
  936. }
  937. # Read more than one arg at a time (-L, -N)
  938. if(defined $opt::L) {
  939. $Global::max_lines = $opt::L;
  940. if(not $opt::pipe) {
  941. # --pipe -L means length of record - not max_number_of_args
  942. $Global::max_number_of_args ||= $Global::max_lines;
  943. }
  944. }
  945. if(defined $opt::max_replace_args) {
  946. $Global::max_number_of_args = $opt::max_replace_args;
  947. $Global::ContextReplace = 1;
  948. }
  949. if((defined $opt::L or defined $opt::max_replace_args)
  950. and
  951. not ($opt::xargs or $opt::m)) {
  952. $Global::ContextReplace = 1;
  953. }
  954. if(defined $opt::tag and not defined $opt::tagstring) {
  955. $opt::tagstring = "\257<\257>"; # Default = {}
  956. }
  957. if(defined $opt::pipepart and
  958. (defined $opt::L or defined $opt::max_lines
  959. or defined $opt::max_replace_args)) {
  960. ::error("--pipepart is incompatible with --max-replace-args, ",
  961. "--max-lines, and -L.\n");
  962. wait_and_exit(255);
  963. }
  964. if(grep /^$Global::arg_sep$|^$Global::arg_file_sep$/o, @ARGV) {
  965. # Deal with ::: and ::::
  966. @ARGV=read_args_from_command_line();
  967. }
  968. # Semaphore defaults
  969. # Must be done before computing number of processes and max_line_length
  970. # because when running as a semaphore GNU Parallel does not read args
  971. $Global::semaphore ||= ($0 =~ m:(^|/)sem$:); # called as 'sem'
  972. if($Global::semaphore) {
  973. # A semaphore does not take input from neither stdin nor file
  974. @opt::a = ("/dev/null");
  975. push(@Global::unget_argv, [Arg->new("")]);
  976. $Semaphore::timeout = $opt::semaphoretimeout || 0;
  977. if(defined $opt::semaphorename) {
  978. $Semaphore::name = $opt::semaphorename;
  979. } else {
  980. $Semaphore::name = `tty`;
  981. chomp $Semaphore::name;
  982. }
  983. $Semaphore::fg = $opt::fg;
  984. $Semaphore::wait = $opt::wait;
  985. $Global::default_simultaneous_sshlogins = 1;
  986. if(not defined $opt::jobs) {
  987. $opt::jobs = 1;
  988. }
  989. if($Global::interactive and $opt::bg) {
  990. ::error("Jobs running in the ".
  991. "background cannot be interactive.\n");
  992. ::wait_and_exit(255);
  993. }
  994. }
  995. if(defined $opt::eta) {
  996. $opt::progress = $opt::eta;
  997. }
  998. if(defined $opt::bar) {
  999. $opt::progress = $opt::bar;
  1000. }
  1001. if(defined $opt::retired) {
  1002. ::error("-g has been retired. Use --group.\n");
  1003. ::error("-B has been retired. Use --bf.\n");
  1004. ::error("-T has been retired. Use --tty.\n");
  1005. ::error("-U has been retired. Use --er.\n");
  1006. ::error("-W has been retired. Use --wd.\n");
  1007. ::error("-Y has been retired. Use --shebang.\n");
  1008. ::error("-H has been retired. Use --halt.\n");
  1009. ::error("--tollef has been retired. Use -u -q --arg-sep -- and --load for -l.\n");
  1010. ::wait_and_exit(255);
  1011. }
  1012. citation_notice();
  1013. parse_sshlogin();
  1014. parse_env_var();
  1015. if(remote_hosts() and ($opt::X or $opt::m or $opt::xargs)) {
  1016. # As we do not know the max line length on the remote machine
  1017. # long commands generated by xargs may fail
  1018. # If opt_N is set, it is probably safe
  1019. ::warning("Using -X or -m with --sshlogin may fail.\n");
  1020. }
  1021. if(not defined $opt::jobs) {
  1022. $opt::jobs = "100%";
  1023. }
  1024. open_joblog();
  1025. }
  1026. sub env_quote {
  1027. # Input:
  1028. # $v = value to quote
  1029. # Returns:
  1030. # $v = value quoted as environment variable
  1031. my $v = $_[0];
  1032. $v =~ s/([\\])/\\$1/g;
  1033. $v =~ s/([\[\] \#\'\&\<\>\(\)\;\{\}\t\"\$\`\*\174\!\?\~])/\\$1/g;
  1034. $v =~ s/\n/"\n"/g;
  1035. return $v;
  1036. }
  1037. sub record_env {
  1038. # Record current %ENV-keys in ~/.parallel/ignored_vars
  1039. # Returns: N/A
  1040. my $ignore_filename = $ENV{'HOME'} . "/.parallel/ignored_vars";
  1041. if(open(my $vars_fh, ">", $ignore_filename)) {
  1042. print $vars_fh map { $_,"\n" } keys %ENV;
  1043. } else {
  1044. ::error("Cannot write to $ignore_filename\n");
  1045. ::wait_and_exit(255);
  1046. }
  1047. }
  1048. sub parse_env_var {
  1049. # Parse --env and set $Global::envvar, $Global::envwarn and $Global::envvarlen
  1050. #
  1051. # Bash functions must be parsed to export them remotely
  1052. # Pre-shellshock style bash function:
  1053. # myfunc=() {...
  1054. # Post-shellshock style bash function:
  1055. # BASH_FUNC_myfunc()=() {...
  1056. #
  1057. # Uses:
  1058. # $Global::envvar = eval string that will set variables in both bash and csh
  1059. # $Global::envwarn = If functions are used: Give warning in csh
  1060. # $Global::envvarlen = length of $Global::envvar
  1061. # @opt::env
  1062. # $Global::shell
  1063. # %ENV
  1064. # Returns: N/A
  1065. $Global::envvar = "";
  1066. $Global::envwarn = "";
  1067. my @vars = ('parallel_bash_environment');
  1068. for my $varstring (@opt::env) {
  1069. # Split up --env VAR1,VAR2
  1070. push @vars, split /,/, $varstring;
  1071. }
  1072. if(grep { /^_$/ } @vars) {
  1073. # --env _
  1074. # Include all vars that are not in a clean environment
  1075. if(open(my $vars_fh, "<", $ENV{'HOME'} . "/.parallel/ignored_vars")) {
  1076. my @ignore = <$vars_fh>;
  1077. chomp @ignore;
  1078. my %ignore;
  1079. @ignore{@ignore} = @ignore;
  1080. close $vars_fh;
  1081. push @vars, grep { not defined $ignore{$_} } keys %ENV;
  1082. @vars = grep { not /^_$/ } @vars;
  1083. } else {
  1084. ::error("Run '$Global::progname --record-env' in a clean environment first.\n");
  1085. ::wait_and_exit(255);
  1086. }
  1087. }
  1088. # Duplicate vars as BASH functions to include post-shellshock functions.
  1089. # So --env myfunc should also look for BASH_FUNC_myfunc()
  1090. @vars = map { $_, "BASH_FUNC_$_()" } @vars;
  1091. # Keep only defined variables
  1092. @vars = grep { defined($ENV{$_}) } @vars;
  1093. # Pre-shellshock style bash function:
  1094. # myfunc=() { echo myfunc
  1095. # }
  1096. # Post-shellshock style bash function:
  1097. # BASH_FUNC_myfunc()=() { echo myfunc
  1098. # }
  1099. my @bash_functions = grep { substr($ENV{$_},0,4) eq "() {" } @vars;
  1100. my @non_functions = grep { substr($ENV{$_},0,4) ne "() {" } @vars;
  1101. if(@bash_functions) {
  1102. # Functions are not supported for all shells
  1103. if($Global::shell !~ m:/(bash|rbash|zsh|rzsh|dash|ksh):) {
  1104. ::warning("Shell functions may not be supported in $Global::shell\n");
  1105. }
  1106. }
  1107. # Pre-shellschock names are without ()
  1108. my @bash_pre_shellshock = grep { not /\(\)/ } @bash_functions;
  1109. # Post-shellschock names are with ()
  1110. my @bash_post_shellshock = grep { /\(\)/ } @bash_functions;
  1111. my @qcsh = (map { my $a=$_; "setenv $a " . env_quote($ENV{$a}) }
  1112. grep { not /^parallel_bash_environment$/ } @non_functions);
  1113. my @qbash = (map { my $a=$_; "export $a=" . env_quote($ENV{$a}) }
  1114. @non_functions, @bash_pre_shellshock);
  1115. push @qbash, map { my $a=$_; "eval $a\"\$$a\"" } @bash_pre_shellshock;
  1116. push @qbash, map { /BASH_FUNC_(.*)\(\)/; "$1 $ENV{$_}" } @bash_post_shellshock;
  1117. #ssh -tt -oLogLevel=quiet lo 'eval `echo PARALLEL_SEQ='$PARALLEL_SEQ'\;export PARALLEL_SEQ\; PARALLEL_PID='$PARALLEL_PID'\;export PARALLEL_PID` ;' tty\ \>/dev/null\ \&\&\ stty\ isig\ -onlcr\ -echo\;echo\ \$SHELL\ \|\ grep\ \"/t\\\{0,1\\\}csh\"\ \>\ /dev/null\ \&\&\ setenv\ BASH_FUNC_myfunc\ \\\(\\\)\\\ \\\{\\\ \\\ echo\\\ a\"'
  1118. #'\"\\\}\ \|\|\ myfunc\(\)\ \{\ \ echo\ a'
  1119. #'\}\ \;myfunc\ 1;
  1120. # Check if any variables contain \n
  1121. if(my @v = map { s/BASH_FUNC_(.*)\(\)/$1/; $_ } grep { $ENV{$_}=~/\n/ } @vars) {
  1122. # \n is bad for csh and will cause it to fail.
  1123. $Global::envwarn = ::shell_quote_scalar(q{echo $SHELL | grep -E "/t?csh" > /dev/null && echo CSH/TCSH DO NOT SUPPORT newlines IN VARIABLES/FUNCTIONS. Unset }."@v".q{ && exec false;}."\n\n") . $Global::envwarn;
  1124. }
  1125. if(not @qcsh) { push @qcsh, "true"; }
  1126. if(not @qbash) { push @qbash, "true"; }
  1127. # Create lines like:
  1128. # echo $SHELL | grep "/t\\{0,1\\}csh" >/dev/null && setenv V1 val1 && setenv V2 val2 || export V1=val1 && export V2=val2 ; echo "$V1$V2"
  1129. if(@vars) {
  1130. $Global::envvar .=
  1131. join"",
  1132. (q{echo $SHELL | grep "/t\\{0,1\\}csh" > /dev/null && }
  1133. . join(" && ", @qcsh)
  1134. . q{ || }
  1135. . join(" && ", @qbash)
  1136. .q{;});
  1137. if($ENV{'parallel_bash_environment'}) {
  1138. $Global::envvar .= 'eval "$parallel_bash_environment";'."\n";
  1139. }
  1140. }
  1141. $Global::envvarlen = length $Global::envvar;
  1142. }
  1143. sub open_joblog {
  1144. # Open joblog as specified by --joblog
  1145. # Uses:
  1146. # $opt::resume
  1147. # $opt::resume_failed
  1148. # $opt::joblog
  1149. # $opt::results
  1150. # $Global::job_already_run
  1151. # %Global::fd
  1152. my $append = 0;
  1153. if(($opt::resume or $opt::resume_failed)
  1154. and
  1155. not ($opt::joblog or $opt::results)) {
  1156. ::error("--resume and --resume-failed require --joblog or --results.\n");
  1157. ::wait_and_exit(255);
  1158. }
  1159. if($opt::joblog) {
  1160. if($opt::resume || $opt::resume_failed) {
  1161. if(open(my $joblog_fh, "<", $opt::joblog)) {
  1162. # Read the joblog
  1163. $append = <$joblog_fh>; # If there is a header: Open as append later
  1164. my $joblog_regexp;
  1165. if($opt::resume_failed) {
  1166. # Make a regexp that only matches commands with exit+signal=0
  1167. # 4 host 1360490623.067 3.445 1023 1222 0 0 command
  1168. $joblog_regexp='^(\d+)(?:\t[^\t]+){5}\t0\t0\t';
  1169. } else {
  1170. # Just match the job number
  1171. $joblog_regexp='^(\d+)';
  1172. }
  1173. while(<$joblog_fh>) {
  1174. if(/$joblog_regexp/o) {
  1175. # This is 30% faster than set_job_already_run($1);
  1176. vec($Global::job_already_run,($1||0),1) = 1;
  1177. } elsif(not /\d+\s+[^\s]+\s+([0-9.]+\s+){6}/) {
  1178. ::error("Format of '$opt::joblog' is wrong: $_");
  1179. ::wait_and_exit(255);
  1180. }
  1181. }
  1182. close $joblog_fh;
  1183. }
  1184. }
  1185. if($append) {
  1186. # Append to joblog
  1187. if(not open($Global::joblog, ">>", $opt::joblog)) {
  1188. ::error("Cannot append to --joblog $opt::joblog.\n");
  1189. ::wait_and_exit(255);
  1190. }
  1191. } else {
  1192. if($opt::joblog eq "-") {
  1193. # Use STDOUT as joblog
  1194. $Global::joblog = $Global::fd{1};
  1195. } elsif(not open($Global::joblog, ">", $opt::joblog)) {
  1196. # Overwrite the joblog
  1197. ::error("Cannot write to --joblog $opt::joblog.\n");
  1198. ::wait_and_exit(255);
  1199. }
  1200. print $Global::joblog
  1201. join("\t", "Seq", "Host", "Starttime", "JobRuntime",
  1202. "Send", "Receive", "Exitval", "Signal", "Command"
  1203. ). "\n";
  1204. }
  1205. }
  1206. }
  1207. sub find_compression_program {
  1208. # Find a fast compression program
  1209. # Returns:
  1210. # $compress_program = compress program with options
  1211. # $decompress_program = decompress program with options
  1212. # Search for these. Sorted by speed
  1213. my @prg = qw(lzop pigz pxz gzip plzip pbzip2 lzma xz lzip bzip2);
  1214. for my $p (@prg) {
  1215. if(which($p)) {
  1216. return ("$p -c -1","$p -dc");
  1217. }
  1218. }
  1219. # Fall back to cat
  1220. return ("cat","cat");
  1221. }
  1222. sub read_options {
  1223. # Read options from command line, profile and $PARALLEL
  1224. # Uses:
  1225. # $opt::shebang_wrap
  1226. # $opt::shebang
  1227. # @ARGV
  1228. # $opt::plain
  1229. # @opt::profile
  1230. # $ENV{'HOME'}
  1231. # $ENV{'PARALLEL'}
  1232. # Returns:
  1233. # @ARGV_no_opt = @ARGV without --options
  1234. # This must be done first as this may exec myself
  1235. if(defined $ARGV[0] and ($ARGV[0] =~ /^--shebang/ or
  1236. $ARGV[0] =~ /^--shebang-?wrap/ or
  1237. $ARGV[0] =~ /^--hashbang/)) {
  1238. # Program is called from #! line in script
  1239. # remove --shebang-wrap if it is set
  1240. $opt::shebang_wrap = ($ARGV[0] =~ s/^--shebang-?wrap *//);
  1241. # remove --shebang if it is set
  1242. $opt::shebang = ($ARGV[0] =~ s/^--shebang *//);
  1243. # remove --hashbang if it is set
  1244. $opt::shebang .= ($ARGV[0] =~ s/^--hashbang *//);
  1245. if($opt::shebang) {
  1246. my $argfile = shell_quote_scalar(pop @ARGV);
  1247. # exec myself to split $ARGV[0] into separate fields
  1248. exec "$0 --skip-first-line -a $argfile @ARGV";
  1249. }
  1250. if($opt::shebang_wrap) {
  1251. my @options;
  1252. my @parser;
  1253. if ($^O eq 'freebsd') {
  1254. # FreeBSD's #! puts different values in @ARGV than Linux' does.
  1255. my @nooptions = @ARGV;
  1256. get_options_from_array(\@nooptions);
  1257. while($#ARGV > $#nooptions) {
  1258. push @options, shift @ARGV;
  1259. }
  1260. while(@ARGV and $ARGV[0] ne ":::") {
  1261. push @parser, shift @ARGV;
  1262. }
  1263. if(@ARGV and $ARGV[0] eq ":::") {
  1264. shift @ARGV;
  1265. }
  1266. } else {
  1267. @options = shift @ARGV;
  1268. }
  1269. my $script = shell_quote_scalar(shift @ARGV);
  1270. # exec myself to split $ARGV[0] into separate fields
  1271. exec "$0 --internal-pipe-means-argfiles @options @parser $script ::: @ARGV";
  1272. }
  1273. }
  1274. Getopt::Long::Configure("bundling","require_order");
  1275. my @ARGV_copy = @ARGV;
  1276. # Check if there is a --profile to set @opt::profile
  1277. get_options_from_array(\@ARGV_copy,"profile|J=s","plain") || die_usage();
  1278. my @ARGV_profile = ();
  1279. my @ARGV_env = ();
  1280. if(not $opt::plain) {
  1281. # Add options from .parallel/config and other profiles
  1282. my @config_profiles = (
  1283. "/etc/parallel/config",
  1284. $ENV{'HOME'}."/.parallel/config",
  1285. $ENV{'HOME'}."/.parallelrc");
  1286. my @profiles = @config_profiles;
  1287. if(@opt::profile) {
  1288. # --profile overrides default profiles
  1289. @profiles = ();
  1290. for my $profile (@opt::profile) {
  1291. if(-r $profile) {
  1292. push @profiles, $profile;
  1293. } else {
  1294. push @profiles, $ENV{'HOME'}."/.parallel/".$profile;
  1295. }
  1296. }
  1297. }
  1298. for my $profile (@profiles) {
  1299. if(-r $profile) {
  1300. open (my $in_fh, "<", $profile) || ::die_bug("read-profile: $profile");
  1301. while(<$in_fh>) {
  1302. /^\s*\#/ and next;
  1303. chomp;
  1304. push @ARGV_profile, shellwords($_);
  1305. }
  1306. close $in_fh;
  1307. } else {
  1308. if(grep /^$profile$/, @config_profiles) {
  1309. # config file is not required to exist
  1310. } else {
  1311. ::error("$profile not readable.\n");
  1312. wait_and_exit(255);
  1313. }
  1314. }
  1315. }
  1316. # Add options from shell variable $PARALLEL
  1317. if($ENV{'PARALLEL'}) {
  1318. @ARGV_env = shellwords($ENV{'PARALLEL'});
  1319. }
  1320. }
  1321. Getopt::Long::Configure("bundling","require_order");
  1322. get_options_from_array(\@ARGV_profile) || die_usage();
  1323. get_options_from_array(\@ARGV_env) || die_usage();
  1324. get_options_from_array(\@ARGV) || die_usage();
  1325. # Prepend non-options to @ARGV (such as commands like 'nice')
  1326. unshift @ARGV, @ARGV_profile, @ARGV_env;
  1327. return @ARGV;
  1328. }
  1329. sub read_args_from_command_line {
  1330. # Arguments given on the command line after:
  1331. # ::: ($Global::arg_sep)
  1332. # :::: ($Global::arg_file_sep)
  1333. # Removes the arguments from @ARGV and:
  1334. # - puts filenames into -a
  1335. # - puts arguments into files and add the files to -a
  1336. # Input:
  1337. # @::ARGV = command option ::: arg arg arg :::: argfiles
  1338. # Uses:
  1339. # $Global::arg_sep
  1340. # $Global::arg_file_sep
  1341. # $opt::internal_pipe_means_argfiles
  1342. # $opt::pipe
  1343. # @opt::a
  1344. # Returns:
  1345. # @argv_no_argsep = @::ARGV without ::: and :::: and following args
  1346. my @new_argv = ();
  1347. for(my $arg = shift @ARGV; @ARGV; $arg = shift @ARGV) {
  1348. if($arg eq $Global::arg_sep
  1349. or
  1350. $arg eq $Global::arg_file_sep) {
  1351. my $group = $arg; # This group of arguments is args or argfiles
  1352. my @group;
  1353. while(defined ($arg = shift @ARGV)) {
  1354. if($arg eq $Global::arg_sep
  1355. or
  1356. $arg eq $Global::arg_file_sep) {
  1357. # exit while loop if finding new separator
  1358. last;
  1359. } else {
  1360. # If not hitting ::: or ::::
  1361. # Append it to the group
  1362. push @group, $arg;
  1363. }
  1364. }
  1365. if($group eq $Global::arg_file_sep
  1366. or ($opt::internal_pipe_means_argfiles and $opt::pipe)
  1367. ) {
  1368. # Group of file names on the command line.
  1369. # Append args into -a
  1370. push @opt::a, @group;
  1371. } elsif($group eq $Global::arg_sep) {
  1372. # Group of arguments on the command line.
  1373. # Put them into a file.
  1374. # Create argfile
  1375. my ($outfh,$name) = ::tmpfile(SUFFIX => ".arg");
  1376. unlink($name);
  1377. # Put args into argfile
  1378. print $outfh map { $_,$/ } @group;
  1379. seek $outfh, 0, 0;
  1380. # Append filehandle to -a
  1381. push @opt::a, $outfh;
  1382. } else {
  1383. ::die_bug("Unknown command line group: $group");
  1384. }
  1385. if(defined($arg)) {
  1386. # $arg is ::: or ::::
  1387. redo;
  1388. } else {
  1389. # $arg is undef -> @ARGV empty
  1390. last;
  1391. }
  1392. }
  1393. push @new_argv, $arg;
  1394. }
  1395. # Output: @ARGV = command to run with options
  1396. return @new_argv;
  1397. }
  1398. sub cleanup {
  1399. # Returns: N/A
  1400. if(@opt::basefile) { cleanup_basefile(); }
  1401. }
  1402. sub __QUOTING_ARGUMENTS_FOR_SHELL__ {}
  1403. sub shell_quote {
  1404. # Input:
  1405. # @strings = strings to be quoted
  1406. # Output:
  1407. # @shell_quoted_strings = string quoted with \ as needed by the shell
  1408. my @strings = (@_);
  1409. for my $a (@strings) {
  1410. $a =~ s/([\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\*\>\<\~\|\; \"\!\$\&\'\202-\377])/\\$1/g;
  1411. $a =~ s/[\n]/'\n'/g; # filenames with '\n' is quoted using \'
  1412. }
  1413. return wantarray ? @strings : "@strings";
  1414. }
  1415. sub shell_quote_empty {
  1416. # Inputs:
  1417. # @strings = strings to be quoted
  1418. # Returns:
  1419. # @quoted_strings = empty strings quoted as ''.
  1420. my @strings = shell_quote(@_);
  1421. for my $a (@strings) {
  1422. if($a eq "") {
  1423. $a = "''";
  1424. }
  1425. }
  1426. return wantarray ? @strings : "@strings";
  1427. }
  1428. sub shell_quote_scalar {
  1429. # Quote the string so shell will not expand any special chars
  1430. # Inputs:
  1431. # $string = string to be quoted
  1432. # Returns:
  1433. # $shell_quoted = string quoted with \ as needed by the shell
  1434. my $a = $_[0];
  1435. if(defined $a) {
  1436. # $a =~ s/([\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\*\>\<\~\|\; \"\!\$\&\'\202-\377])/\\$1/g;
  1437. # This is 1% faster than the above
  1438. $a =~ s/[\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\*\>\<\~\|\; \"\!\$\&\'\202-\377]/\\$&/go;
  1439. $a =~ s/[\n]/'\n'/go; # filenames with '\n' is quoted using \'
  1440. }
  1441. return $a;
  1442. }
  1443. sub shell_quote_file {
  1444. # Quote the string so shell will not expand any special chars and prepend ./ if needed
  1445. # Input:
  1446. # $filename = filename to be shell quoted
  1447. # Returns:
  1448. # $quoted_filename = filename quoted with \ as needed by the shell and ./ if needed
  1449. my $a = shell_quote_scalar(shift);
  1450. if(defined $a) {
  1451. if($a =~ m:^/: or $a =~ m:^\./:) {
  1452. # /abs/path or ./rel/path => skip
  1453. } else {
  1454. # rel/path => ./rel/path
  1455. $a = "./".$a;
  1456. }
  1457. }
  1458. return $a;
  1459. }
  1460. sub shellwords {
  1461. # Input:
  1462. # $string = shell line
  1463. # Returns:
  1464. # @shell_words = $string split into words as shell would do
  1465. $Global::use{"Text::ParseWords"} ||= eval "use Text::ParseWords; 1;";
  1466. return Text::ParseWords::shellwords(@_);
  1467. }
  1468. sub __FILEHANDLES__ {}
  1469. sub save_stdin_stdout_stderr {
  1470. # Remember the original STDIN, STDOUT and STDERR
  1471. # and file descriptors opened by the shell (e.g. 3>/tmp/foo)
  1472. # Uses:
  1473. # %Global::fd
  1474. # $Global::original_stderr
  1475. # $Global::original_stdin
  1476. # Returns: N/A
  1477. # Find file descriptors that are already opened (by the shell)
  1478. for my $fdno (1..61) {
  1479. # /dev/fd/62 and above are used by bash for <(cmd)
  1480. my $fh;
  1481. # 2-argument-open is used to be compatible with old perl 5.8.0
  1482. # bug #43570: Perl 5.8.0 creates 61 files
  1483. if(open($fh,">&=$fdno")) {
  1484. $Global::fd{$fdno}=$fh;
  1485. }
  1486. }
  1487. open $Global::original_stderr, ">&", "STDERR" or
  1488. ::die_bug("Can't dup STDERR: $!");
  1489. open $Global::original_stdin, "<&", "STDIN" or
  1490. ::die_bug("Can't dup STDIN: $!");
  1491. $Global::is_terminal = (-t $Global::original_stderr) && !$ENV{'CIRCLECI'}&& !$ENV{'GITHUB_ACTIONS'} && !$ENV{'TRAVIS'};
  1492. }
  1493. sub enough_file_handles {
  1494. # Check that we have enough filehandles available for starting
  1495. # another job
  1496. # Uses:
  1497. # $opt::ungroup
  1498. # %Global::fd
  1499. # Returns:
  1500. # 1 if ungrouped (thus not needing extra filehandles)
  1501. # 0 if too few filehandles
  1502. # 1 if enough filehandles
  1503. if(not $opt::ungroup) {
  1504. my %fh;
  1505. my $enough_filehandles = 1;
  1506. # perl uses 7 filehandles for something?
  1507. # open3 uses 2 extra filehandles temporarily
  1508. # We need a filehandle for each redirected file descriptor
  1509. # (normally just STDOUT and STDERR)
  1510. for my $i (1..(7+2+keys %Global::fd)) {
  1511. $enough_filehandles &&= open($fh{$i}, "<", "/dev/null");
  1512. }
  1513. for (values %fh) { close $_; }
  1514. return $enough_filehandles;
  1515. } else {
  1516. # Ungrouped does not need extra file handles
  1517. return 1;
  1518. }
  1519. }
  1520. sub open_or_exit {
  1521. # Open a file name or exit if the file cannot be opened
  1522. # Inputs:
  1523. # $file = filehandle or filename to open
  1524. # Uses:
  1525. # $Global::stdin_in_opt_a
  1526. # $Global::original_stdin
  1527. # Returns:
  1528. # $fh = file handle to read-opened file
  1529. my $file = shift;
  1530. if($file eq "-") {
  1531. $Global::stdin_in_opt_a = 1;
  1532. return ($Global::original_stdin || *STDIN);
  1533. }
  1534. if(ref $file eq "GLOB") {
  1535. # This is an open filehandle
  1536. return $file;
  1537. }
  1538. my $fh = gensym;
  1539. if(not open($fh, "<", $file)) {
  1540. ::error("Cannot open input file `$file': No such file or directory.\n");
  1541. wait_and_exit(255);
  1542. }
  1543. return $fh;
  1544. }
  1545. sub __RUNNING_THE_JOBS_AND_PRINTING_PROGRESS__ {}
  1546. # Variable structure:
  1547. #
  1548. # $Global::running{$pid} = Pointer to Job-object
  1549. # @Global::virgin_jobs = Pointer to Job-object that have received no input
  1550. # $Global::host{$sshlogin} = Pointer to SSHLogin-object
  1551. # $Global::total_running = total number of running jobs
  1552. # $Global::total_started = total jobs started
  1553. sub init_run_jobs {
  1554. $Global::total_running = 0;
  1555. $Global::total_started = 0;
  1556. $Global::tty_taken = 0;
  1557. $SIG{USR1} = \&list_running_jobs;
  1558. $SIG{USR2} = \&toggle_progress;
  1559. if(@opt::basefile) { setup_basefile(); }
  1560. }
  1561. {
  1562. my $last_time;
  1563. my %last_mtime;
  1564. sub start_more_jobs {
  1565. # Run start_another_job() but only if:
  1566. # * not $Global::start_no_new_jobs set
  1567. # * not JobQueue is empty
  1568. # * not load on server is too high
  1569. # * not server swapping
  1570. # * not too short time since last remote login
  1571. # Uses:
  1572. # $Global::max_procs_file
  1573. # $Global::max_procs_file_last_mod
  1574. # %Global::host
  1575. # @opt::sshloginfile
  1576. # $Global::start_no_new_jobs
  1577. # $opt::filter_hosts
  1578. # $Global::JobQueue
  1579. # $opt::pipe
  1580. # $opt::load
  1581. # $opt::noswap
  1582. # $opt::delay
  1583. # $Global::newest_starttime
  1584. # Returns:
  1585. # $jobs_started = number of jobs started
  1586. my $jobs_started = 0;
  1587. my $jobs_started_this_round = 0;
  1588. if($Global::start_no_new_jobs) {
  1589. return $jobs_started;
  1590. }
  1591. if(time - ($last_time||0) > 1) {
  1592. # At most do this every second
  1593. $last_time = time;
  1594. if($Global::max_procs_file) {
  1595. # --jobs filename
  1596. my $mtime = (stat($Global::max_procs_file))[9];
  1597. if($mtime > $Global::max_procs_file_last_mod) {
  1598. # file changed: Force re-computing max_jobs_running
  1599. $Global::max_procs_file_last_mod = $mtime;
  1600. for my $sshlogin (values %Global::host) {
  1601. $sshlogin->set_max_jobs_running(undef);
  1602. }
  1603. }
  1604. }
  1605. if(@opt::sshloginfile) {
  1606. # Is --sshloginfile changed?
  1607. for my $slf (@opt::sshloginfile) {
  1608. my $actual_file = expand_slf_shorthand($slf);
  1609. my $mtime = (stat($actual_file))[9];
  1610. $last_mtime{$actual_file} ||= $mtime;
  1611. if($mtime - $last_mtime{$actual_file} > 1) {
  1612. ::debug("run","--sshloginfile $actual_file changed. reload\n");
  1613. $last_mtime{$actual_file} = $mtime;
  1614. # Reload $slf
  1615. # Empty sshlogins
  1616. @Global::sshlogin = ();
  1617. for (values %Global::host) {
  1618. # Don't start new jobs on any host
  1619. # except the ones added back later
  1620. $_->set_max_jobs_running(0);
  1621. }
  1622. # This will set max_jobs_running on the SSHlogins
  1623. read_sshloginfile($actual_file);
  1624. parse_sshlogin();
  1625. $opt::filter_hosts and filter_hosts();
  1626. setup_basefile();
  1627. }
  1628. }
  1629. }
  1630. }
  1631. do {
  1632. $jobs_started_this_round = 0;
  1633. # This will start 1 job on each --sshlogin (if possible)
  1634. # thus distribute the jobs on the --sshlogins round robin
  1635. for my $sshlogin (values %Global::host) {
  1636. if($Global::JobQueue->empty() and not $opt::pipe) {
  1637. # No more jobs in the queue
  1638. last;
  1639. }
  1640. debug("run", "Running jobs before on ", $sshlogin->string(), ": ",
  1641. $sshlogin->jobs_running(), "\n");
  1642. if ($sshlogin->jobs_running() < $sshlogin->max_jobs_running()) {
  1643. if($opt::load and $sshlogin->loadavg_too_high()) {
  1644. # The load is too high or unknown
  1645. next;
  1646. }
  1647. if($opt::noswap and $sshlogin->swapping()) {
  1648. # The server is swapping
  1649. next;
  1650. }
  1651. if($sshlogin->too_fast_remote_login()) {
  1652. # It has been too short since
  1653. next;
  1654. }
  1655. if($opt::delay and $opt::delay > ::now() - $Global::newest_starttime) {
  1656. # It has been too short since last start
  1657. next;
  1658. }
  1659. debug("run", $sshlogin->string(), " has ", $sshlogin->jobs_running(),
  1660. " out of ", $sshlogin->max_jobs_running(),
  1661. " jobs running. Start another.\n");
  1662. if(start_another_job($sshlogin) == 0) {
  1663. # No more jobs to start on this $sshlogin
  1664. debug("run","No jobs started on ", $sshlogin->string(), "\n");
  1665. next;
  1666. }
  1667. $sshlogin->inc_jobs_running();
  1668. $sshlogin->set_last_login_at(::now());
  1669. $jobs_started++;
  1670. $jobs_started_this_round++;
  1671. }
  1672. debug("run","Running jobs after on ", $sshlogin->string(), ": ",
  1673. $sshlogin->jobs_running(), " of ",
  1674. $sshlogin->max_jobs_running(), "\n");
  1675. }
  1676. } while($jobs_started_this_round);
  1677. return $jobs_started;
  1678. }
  1679. }
  1680. {
  1681. my $no_more_file_handles_warned;
  1682. sub start_another_job {
  1683. # If there are enough filehandles
  1684. # and JobQueue not empty
  1685. # and not $job is in joblog
  1686. # Then grab a job from Global::JobQueue,
  1687. # start it at sshlogin
  1688. # mark it as virgin_job
  1689. # Inputs:
  1690. # $sshlogin = the SSHLogin to start the job on
  1691. # Uses:
  1692. # $Global::JobQueue
  1693. # $opt::pipe
  1694. # $opt::results
  1695. # $opt::resume
  1696. # @Global::virgin_jobs
  1697. # Returns:
  1698. # 1 if another jobs was started
  1699. # 0 otherwise
  1700. my $sshlogin = shift;
  1701. # Do we have enough file handles to start another job?
  1702. if(enough_file_handles()) {
  1703. if($Global::JobQueue->empty() and not $opt::pipe) {
  1704. # No more commands to run
  1705. debug("start", "Not starting: JobQueue empty\n");
  1706. return 0;
  1707. } else {
  1708. my $job;
  1709. # Skip jobs already in job log
  1710. # Skip jobs already in results
  1711. do {
  1712. $job = get_job_with_sshlogin($sshlogin);
  1713. if(not defined $job) {
  1714. # No command available for that sshlogin
  1715. debug("start", "Not starting: no jobs available for ",
  1716. $sshlogin->string(), "\n");
  1717. return 0;
  1718. }
  1719. } while ($job->is_already_in_joblog()
  1720. or
  1721. ($opt::results and $opt::resume and $job->is_already_in_results()));
  1722. debug("start", "Command to run on '", $job->sshlogin()->string(), "': '",
  1723. $job->replaced(),"'\n");
  1724. if($job->start()) {
  1725. if($opt::pipe) {
  1726. push(@Global::virgin_jobs,$job);
  1727. }
  1728. debug("start", "Started as seq ", $job->seq(),
  1729. " pid:", $job->pid(), "\n");
  1730. return 1;
  1731. } else {
  1732. # Not enough processes to run the job.
  1733. # Put it back on the queue.
  1734. $Global::JobQueue->unget($job);
  1735. # Count down the number of jobs to run for this SSHLogin.
  1736. my $max = $sshlogin->max_jobs_running();
  1737. if($max > 1) { $max--; } else {
  1738. ::error("No more processes: cannot run a single job. Something is wrong.\n");
  1739. ::wait_and_exit(255);
  1740. }
  1741. $sshlogin->set_max_jobs_running($max);
  1742. # Sleep up to 300 ms to give other processes time to die
  1743. ::usleep(rand()*300);
  1744. ::warning("No more processes: ",
  1745. "Decreasing number of running jobs to $max. ",
  1746. "Raising ulimit -u or /etc/security/limits.conf may help.\n");
  1747. return 0;
  1748. }
  1749. }
  1750. } else {
  1751. # No more file handles
  1752. $no_more_file_handles_warned++ or
  1753. ::warning("No more file handles. ",
  1754. "Raising ulimit -n or /etc/security/limits.conf may help.\n");
  1755. return 0;
  1756. }
  1757. }
  1758. }
  1759. $opt::min_progress_interval = 0;
  1760. sub init_progress {
  1761. # Uses:
  1762. # $opt::bar
  1763. # Returns:
  1764. # list of computers for progress output
  1765. $|=1;
  1766. if (not $Global::is_terminal) {
  1767. $opt::min_progress_interval = 30;
  1768. }
  1769. if($opt::bar) {
  1770. return("","");
  1771. }
  1772. my %progress = progress();
  1773. return ("\nComputers / CPU cores / Max jobs to run\n",
  1774. $progress{'workerlist'});
  1775. }
  1776. sub drain_job_queue {
  1777. # Uses:
  1778. # $opt::progress
  1779. # $Global::original_stderr
  1780. # $Global::total_running
  1781. # $Global::max_jobs_running
  1782. # %Global::running
  1783. # $Global::JobQueue
  1784. # %Global::host
  1785. # $Global::start_no_new_jobs
  1786. # Returns: N/A
  1787. if($opt::progress) {
  1788. print $Global::original_stderr init_progress();
  1789. }
  1790. my $last_header="";
  1791. my $sleep = 0.2;
  1792. my $last_left = 1000000000;
  1793. my $last_progress_time = 0;
  1794. my $ps_reported = 0;
  1795. do {
  1796. while($Global::total_running > 0) {
  1797. debug($Global::total_running, "==", scalar
  1798. keys %Global::running," slots: ", $Global::max_jobs_running);
  1799. if($opt::pipe) {
  1800. # When using --pipe sometimes file handles are not closed properly
  1801. for my $job (values %Global::running) {
  1802. close $job->fh(0,"w");
  1803. }
  1804. }
  1805. # When not connected to terminal, assume CI (e.g. CircleCI). In
  1806. # that case we want occasional progress output to prevent abort
  1807. # due to timeout with no output, but we also need to stop sending
  1808. # progress output if there has been no actual progress, so that
  1809. # the job can time out appropriately (CirecleCI: 10m) in case of
  1810. # a hung test. But without special output, it is extremely
  1811. # annoying to diagnose which test is hung, so we add that using
  1812. # `ps` below.
  1813. if($opt::progress and
  1814. ($Global::is_terminal or (time() - $last_progress_time) >= 30)) {
  1815. my %progress = progress();
  1816. if($last_header ne $progress{'header'}) {
  1817. print $Global::original_stderr "\n", $progress{'header'}, "\n";
  1818. $last_header = $progress{'header'};
  1819. }
  1820. if ($Global::is_terminal) {
  1821. print $Global::original_stderr "\r",$progress{'status'};
  1822. }
  1823. if ($last_left > $Global::left) {
  1824. if (not $Global::is_terminal) {
  1825. print $Global::original_stderr $progress{'status'},"\n";
  1826. }
  1827. $last_progress_time = time();
  1828. $ps_reported = 0;
  1829. } elsif (not $ps_reported and (time() - $last_progress_time) >= 60) {
  1830. # No progress in at least 60 seconds: run ps
  1831. print $Global::original_stderr "\n";
  1832. my $script_dir = ::dirname($0);
  1833. system("$script_dir/ps_with_stack || ps -wwf");
  1834. $ps_reported = 1;
  1835. }
  1836. $last_left = $Global::left;
  1837. flush $Global::original_stderr;
  1838. }
  1839. if($Global::total_running < $Global::max_jobs_running
  1840. and not $Global::JobQueue->empty()) {
  1841. # These jobs may not be started because of loadavg
  1842. # or too little time between each ssh login.
  1843. if(start_more_jobs() > 0) {
  1844. # Exponential back-on if jobs were started
  1845. $sleep = $sleep/2+0.001;
  1846. }
  1847. }
  1848. # Sometimes SIGCHLD is not registered, so force reaper
  1849. $sleep = ::reap_usleep($sleep);
  1850. }
  1851. if(not $Global::JobQueue->empty()) {
  1852. # These jobs may not be started:
  1853. # * because there the --filter-hosts has removed all
  1854. if(not %Global::host) {
  1855. ::error("There are no hosts left to run on.\n");
  1856. ::wait_and_exit(255);
  1857. }
  1858. # * because of loadavg
  1859. # * because of too little time between each ssh login.
  1860. start_more_jobs();
  1861. $sleep = ::reap_usleep($sleep);
  1862. if($Global::max_jobs_running == 0) {
  1863. ::warning("There are no job slots available. Increase --jobs.\n");
  1864. }
  1865. }
  1866. } while ($Global::total_running > 0
  1867. or
  1868. not $Global::start_no_new_jobs and not $Global::JobQueue->empty());
  1869. if($opt::progress) {
  1870. my %progress = progress();
  1871. print $Global::original_stderr $opt::progress_sep, $progress{'status'}, "\n";
  1872. flush $Global::original_stderr;
  1873. }
  1874. }
  1875. sub toggle_progress {
  1876. # Turn on/off progress view
  1877. # Uses:
  1878. # $opt::progress
  1879. # $Global::original_stderr
  1880. # Returns: N/A
  1881. $opt::progress = not $opt::progress;
  1882. if($opt::progress) {
  1883. print $Global::original_stderr init_progress();
  1884. }
  1885. }
  1886. sub progress {
  1887. # Uses:
  1888. # $opt::bar
  1889. # $opt::eta
  1890. # %Global::host
  1891. # $Global::total_started
  1892. # Returns:
  1893. # $workerlist = list of workers
  1894. # $header = that will fit on the screen
  1895. # $status = message that will fit on the screen
  1896. if($opt::bar) {
  1897. return ("workerlist" => "", "header" => "", "status" => bar());
  1898. }
  1899. my $eta = "";
  1900. my ($status,$header)=("","");
  1901. if($opt::eta) {
  1902. my($total, $completed, $left, $pctcomplete, $avgtime, $this_eta) =
  1903. compute_eta();
  1904. $eta = sprintf("ETA: %ds Left: %d AVG: %.2fs ",
  1905. $this_eta, $left, $avgtime);
  1906. $Global::left = $left;
  1907. }
  1908. my $termcols = terminal_columns();
  1909. my @workers = sort keys %Global::host;
  1910. my %sshlogin = map { $_ eq ":" ? ($_=>"local") : ($_=>$_) } @workers;
  1911. my $workerno = 1;
  1912. my %workerno = map { ($_=>$workerno++) } @workers;
  1913. my $workerlist = "";
  1914. for my $w (@workers) {
  1915. $workerlist .=
  1916. $workerno{$w}.":".$sshlogin{$w} ." / ".
  1917. ($Global::host{$w}->ncpus() || "-")." / ".
  1918. $Global::host{$w}->max_jobs_running()."\n";
  1919. }
  1920. $status = "x"x($termcols+1);
  1921. if(length $status > $termcols) {
  1922. # sshlogin1:XX/XX/XX%/XX.Xs sshlogin2:XX/XX/XX%/XX.Xs sshlogin3:XX/XX/XX%/XX.Xs
  1923. $header = "Computer:jobs running/jobs completed/%of started jobs/Average seconds to complete";
  1924. $status = $eta .
  1925. join(" ",map
  1926. {
  1927. if($Global::total_started) {
  1928. my $completed = ($Global::host{$_}->jobs_completed()||0);
  1929. my $running = $Global::host{$_}->jobs_running();
  1930. my $time = $completed ? (time-$^T)/($completed) : "0";
  1931. sprintf("%s:%d/%d/%d%%/%.1fs ",
  1932. $sshlogin{$_}, $running, $completed,
  1933. ($running+$completed)*100
  1934. / $Global::total_started, $time);
  1935. }
  1936. } @workers);
  1937. }
  1938. if(length $status > $termcols) {
  1939. # 1:XX/XX/XX%/XX.Xs 2:XX/XX/XX%/XX.Xs 3:XX/XX/XX%/XX.Xs 4:XX/XX/XX%/XX.Xs
  1940. $header = "Computer:jobs running/jobs completed/%of started jobs";
  1941. $status = $eta .
  1942. join(" ",map
  1943. {
  1944. my $completed = ($Global::host{$_}->jobs_completed()||0);
  1945. my $running = $Global::host{$_}->jobs_running();
  1946. my $time = $completed ? (time-$^T)/($completed) : "0";
  1947. sprintf("%s:%d/%d/%d%%/%.1fs ",
  1948. $workerno{$_}, $running, $completed,
  1949. ($running+$completed)*100
  1950. / $Global::total_started, $time);
  1951. } @workers);
  1952. }
  1953. if(length $status > $termcols) {
  1954. # sshlogin1:XX/XX/XX% sshlogin2:XX/XX/XX% sshlogin3:XX/XX/XX%
  1955. $header = "Computer:jobs running/jobs completed/%of started jobs";
  1956. $status = $eta .
  1957. join(" ",map
  1958. { sprintf("%s:%d/%d/%d%%",
  1959. $sshlogin{$_},
  1960. $Global::host{$_}->jobs_running(),
  1961. ($Global::host{$_}->jobs_completed()||0),
  1962. ($Global::host{$_}->jobs_running()+
  1963. ($Global::host{$_}->jobs_completed()||0))*100
  1964. / $Global::total_started) }
  1965. @workers);
  1966. }
  1967. if(length $status > $termcols) {
  1968. # 1:XX/XX/XX% 2:XX/XX/XX% 3:XX/XX/XX% 4:XX/XX/XX% 5:XX/XX/XX% 6:XX/XX/XX%
  1969. $header = "Computer:jobs running/jobs completed/%of started jobs";
  1970. $status = $eta .
  1971. join(" ",map
  1972. { sprintf("%s:%d/%d/%d%%",
  1973. $workerno{$_},
  1974. $Global::host{$_}->jobs_running(),
  1975. ($Global::host{$_}->jobs_completed()||0),
  1976. ($Global::host{$_}->jobs_running()+
  1977. ($Global::host{$_}->jobs_completed()||0))*100
  1978. / $Global::total_started) }
  1979. @workers);
  1980. }
  1981. if(length $status > $termcols) {
  1982. # sshlogin1:XX/XX/XX% sshlogin2:XX/XX/XX% sshlogin3:XX/XX sshlogin4:XX/XX
  1983. $header = "Computer:jobs running/jobs completed";
  1984. $status = $eta .
  1985. join(" ",map
  1986. { sprintf("%s:%d/%d",
  1987. $sshlogin{$_}, $Global::host{$_}->jobs_running(),
  1988. ($Global::host{$_}->jobs_completed()||0)) }
  1989. @workers);
  1990. }
  1991. if(length $status > $termcols) {
  1992. # sshlogin1:XX/XX sshlogin2:XX/XX sshlogin3:XX/XX sshlogin4:XX/XX
  1993. $header = "Computer:jobs running/jobs completed";
  1994. $status = $eta .
  1995. join(" ",map
  1996. { sprintf("%s:%d/%d",
  1997. $sshlogin{$_}, $Global::host{$_}->jobs_running(),
  1998. ($Global::host{$_}->jobs_completed()||0)) }
  1999. @workers);
  2000. }
  2001. if(length $status > $termcols) {
  2002. # 1:XX/XX 2:XX/XX 3:XX/XX 4:XX/XX 5:XX/XX 6:XX/XX
  2003. $header = "Computer:jobs running/jobs completed";
  2004. $status = $eta .
  2005. join(" ",map
  2006. { sprintf("%s:%d/%d",
  2007. $workerno{$_}, $Global::host{$_}->jobs_running(),
  2008. ($Global::host{$_}->jobs_completed()||0)) }
  2009. @workers);
  2010. }
  2011. if(length $status > $termcols) {
  2012. # sshlogin1:XX sshlogin2:XX sshlogin3:XX sshlogin4:XX sshlogin5:XX
  2013. $header = "Computer:jobs completed";
  2014. $status = $eta .
  2015. join(" ",map
  2016. { sprintf("%s:%d",
  2017. $sshlogin{$_},
  2018. ($Global::host{$_}->jobs_completed()||0)) }
  2019. @workers);
  2020. }
  2021. if(length $status > $termcols) {
  2022. # 1:XX 2:XX 3:XX 4:XX 5:XX 6:XX
  2023. $header = "Computer:jobs completed";
  2024. $status = $eta .
  2025. join(" ",map
  2026. { sprintf("%s:%d",
  2027. $workerno{$_},
  2028. ($Global::host{$_}->jobs_completed()||0)) }
  2029. @workers);
  2030. }
  2031. return ("workerlist" => $workerlist, "header" => $header, "status" => $status);
  2032. }
  2033. {
  2034. my ($total, $first_completed, $smoothed_avg_time);
  2035. sub compute_eta {
  2036. # Calculate important numbers for ETA
  2037. # Returns:
  2038. # $total = number of jobs in total
  2039. # $completed = number of jobs completed
  2040. # $left = number of jobs left
  2041. # $pctcomplete = percent of jobs completed
  2042. # $avgtime = averaged time
  2043. # $eta = smoothed eta
  2044. $total ||= $Global::JobQueue->total_jobs();
  2045. my $completed = 0;
  2046. for(values %Global::host) { $completed += $_->jobs_completed() }
  2047. my $left = $total - $completed;
  2048. if(not $completed) {
  2049. return($total, $completed, $left, 0, 0, 0);
  2050. }
  2051. my $pctcomplete = $completed / $total;
  2052. $first_completed ||= time;
  2053. my $timepassed = (time - $first_completed);
  2054. my $avgtime = $timepassed / $completed;
  2055. $smoothed_avg_time ||= $avgtime;
  2056. # Smooth the eta so it does not jump wildly
  2057. $smoothed_avg_time = (1 - $pctcomplete) * $smoothed_avg_time +
  2058. $pctcomplete * $avgtime;
  2059. my $eta = int($left * $smoothed_avg_time);
  2060. return($total, $completed, $left, $pctcomplete, $avgtime, $eta);
  2061. }
  2062. }
  2063. {
  2064. my ($rev,$reset);
  2065. sub bar {
  2066. # Return:
  2067. # $status = bar with eta, completed jobs, arg and pct
  2068. $rev ||= "\033[7m";
  2069. $reset ||= "\033[0m";
  2070. my($total, $completed, $left, $pctcomplete, $avgtime, $eta) =
  2071. compute_eta();
  2072. my $arg = $Global::newest_job ?
  2073. $Global::newest_job->{'commandline'}->replace_placeholders(["\257<\257>"],0,0) : "";
  2074. # These chars mess up display in the terminal
  2075. $arg =~ tr/[\011-\016\033\302-\365]//d;
  2076. my $bar_text =
  2077. sprintf("%d%% %d:%d=%ds %s",
  2078. $pctcomplete*100, $completed, $left, $eta, $arg);
  2079. my $terminal_width = terminal_columns();
  2080. my $s = sprintf("%-${terminal_width}s",
  2081. substr($bar_text." "x$terminal_width,
  2082. 0,$terminal_width));
  2083. my $width = int($terminal_width * $pctcomplete);
  2084. substr($s,$width,0) = $reset;
  2085. my $zenity = sprintf("%-${terminal_width}s",
  2086. substr("# $eta sec $arg",
  2087. 0,$terminal_width));
  2088. $s = "\r" . $zenity . "\r" . $pctcomplete*100 . # Prefix with zenity header
  2089. "\r" . $rev . $s . $reset;
  2090. return $s;
  2091. }
  2092. }
  2093. {
  2094. my ($columns,$last_column_time);
  2095. sub terminal_columns {
  2096. # Get the number of columns of the display
  2097. # Returns:
  2098. # number of columns of the screen
  2099. if(not $columns or $last_column_time < time) {
  2100. $last_column_time = time;
  2101. $columns = $ENV{'COLUMNS'};
  2102. if(not $columns) {
  2103. my $resize = qx{ resize 2>/dev/null };
  2104. $resize =~ /COLUMNS=(\d+);/ and do { $columns = $1; };
  2105. }
  2106. $columns ||= 80;
  2107. }
  2108. return $columns;
  2109. }
  2110. }
  2111. sub get_job_with_sshlogin {
  2112. # Returns:
  2113. # next job object for $sshlogin if any available
  2114. my $sshlogin = shift;
  2115. my $job = undef;
  2116. if ($opt::hostgroups) {
  2117. my @other_hostgroup_jobs = ();
  2118. while($job = $Global::JobQueue->get()) {
  2119. if($sshlogin->in_hostgroups($job->hostgroups())) {
  2120. # Found a job for this hostgroup
  2121. last;
  2122. } else {
  2123. # This job was not in the hostgroups of $sshlogin
  2124. push @other_hostgroup_jobs, $job;
  2125. }
  2126. }
  2127. $Global::JobQueue->unget(@other_hostgroup_jobs);
  2128. if(not defined $job) {
  2129. # No more jobs
  2130. return undef;
  2131. }
  2132. } else {
  2133. $job = $Global::JobQueue->get();
  2134. if(not defined $job) {
  2135. # No more jobs
  2136. ::debug("start", "No more jobs: JobQueue empty\n");
  2137. return undef;
  2138. }
  2139. }
  2140. my $clean_command = $job->replaced();
  2141. if($clean_command =~ /^\s*$/) {
  2142. # Do not run empty lines
  2143. if(not $Global::JobQueue->empty()) {
  2144. return get_job_with_sshlogin($sshlogin);
  2145. } else {
  2146. return undef;
  2147. }
  2148. }
  2149. $job->set_sshlogin($sshlogin);
  2150. if($opt::retries and $clean_command and
  2151. $job->failed_here()) {
  2152. # This command with these args failed for this sshlogin
  2153. my ($no_of_failed_sshlogins,$min_failures) = $job->min_failed();
  2154. # Only look at the Global::host that have > 0 jobslots
  2155. if($no_of_failed_sshlogins == grep { $_->max_jobs_running() > 0 } values %Global::host
  2156. and $job->failed_here() == $min_failures) {
  2157. # It failed the same or more times on another host:
  2158. # run it on this host
  2159. } else {
  2160. # If it failed fewer times on another host:
  2161. # Find another job to run
  2162. my $nextjob;
  2163. if(not $Global::JobQueue->empty()) {
  2164. # This can potentially recurse for all args
  2165. no warnings 'recursion';
  2166. $nextjob = get_job_with_sshlogin($sshlogin);
  2167. }
  2168. # Push the command back on the queue
  2169. $Global::JobQueue->unget($job);
  2170. return $nextjob;
  2171. }
  2172. }
  2173. return $job;
  2174. }
  2175. sub __REMOTE_SSH__ {}
  2176. sub read_sshloginfiles {
  2177. # Returns: N/A
  2178. for my $s (@_) {
  2179. read_sshloginfile(expand_slf_shorthand($s));
  2180. }
  2181. }
  2182. sub expand_slf_shorthand {
  2183. my $file = shift;
  2184. if($file eq "-") {
  2185. # skip: It is stdin
  2186. } elsif($file eq "..") {
  2187. $file = $ENV{'HOME'}."/.parallel/sshloginfile";
  2188. } elsif($file eq ".") {
  2189. $file = "/etc/parallel/sshloginfile";
  2190. } elsif(not -r $file) {
  2191. if(not -r $ENV{'HOME'}."/.parallel/".$file) {
  2192. # Try prepending ~/.parallel
  2193. ::error("Cannot open $file.\n");
  2194. ::wait_and_exit(255);
  2195. } else {
  2196. $file = $ENV{'HOME'}."/.parallel/".$file;
  2197. }
  2198. }
  2199. return $file;
  2200. }
  2201. sub read_sshloginfile {
  2202. # Returns: N/A
  2203. my $file = shift;
  2204. my $close = 1;
  2205. my $in_fh;
  2206. ::debug("init","--slf ",$file);
  2207. if($file eq "-") {
  2208. $in_fh = *STDIN;
  2209. $close = 0;
  2210. } else {
  2211. if(not open($in_fh, "<", $file)) {
  2212. # Try the filename
  2213. ::error("Cannot open $file.\n");
  2214. ::wait_and_exit(255);
  2215. }
  2216. }
  2217. while(<$in_fh>) {
  2218. chomp;
  2219. /^\s*#/ and next;
  2220. /^\s*$/ and next;
  2221. push @Global::sshlogin, $_;
  2222. }
  2223. if($close) {
  2224. close $in_fh;
  2225. }
  2226. }
  2227. sub parse_sshlogin {
  2228. # Returns: N/A
  2229. my @login;
  2230. if(not @Global::sshlogin) { @Global::sshlogin = (":"); }
  2231. for my $sshlogin (@Global::sshlogin) {
  2232. # Split up -S sshlogin,sshlogin
  2233. for my $s (split /,/, $sshlogin) {
  2234. if ($s eq ".." or $s eq "-") {
  2235. # This may add to @Global::sshlogin - possibly bug
  2236. read_sshloginfile(expand_slf_shorthand($s));
  2237. } else {
  2238. push (@login, $s);
  2239. }
  2240. }
  2241. }
  2242. $Global::minimal_command_line_length = 8_000_000;
  2243. my @allowed_hostgroups;
  2244. for my $ncpu_sshlogin_string (::uniq(@login)) {
  2245. my $sshlogin = SSHLogin->new($ncpu_sshlogin_string);
  2246. my $sshlogin_string = $sshlogin->string();
  2247. if($sshlogin_string eq "") {
  2248. # This is an ssh group: -S @webservers
  2249. push @allowed_hostgroups, $sshlogin->hostgroups();
  2250. next;
  2251. }
  2252. if($Global::host{$sshlogin_string}) {
  2253. # This sshlogin has already been added:
  2254. # It is probably a host that has come back
  2255. # Set the max_jobs_running back to the original
  2256. debug("run","Already seen $sshlogin_string\n");
  2257. if($sshlogin->{'ncpus'}) {
  2258. # If ncpus set by '#/' of the sshlogin, overwrite it:
  2259. $Global::host{$sshlogin_string}->set_ncpus($sshlogin->ncpus());
  2260. }
  2261. $Global::host{$sshlogin_string}->set_max_jobs_running(undef);
  2262. next;
  2263. }
  2264. if($sshlogin_string eq ":") {
  2265. $sshlogin->set_maxlength(Limits::Command::max_length());
  2266. } else {
  2267. # If all chars needs to be quoted, every other character will be \
  2268. $sshlogin->set_maxlength(int(Limits::Command::max_length()/2));
  2269. }
  2270. $Global::minimal_command_line_length =
  2271. ::min($Global::minimal_command_line_length, $sshlogin->maxlength());
  2272. $Global::host{$sshlogin_string} = $sshlogin;
  2273. }
  2274. if(@allowed_hostgroups) {
  2275. # Remove hosts that are not in these groups
  2276. while (my ($string, $sshlogin) = each %Global::host) {
  2277. if(not $sshlogin->in_hostgroups(@allowed_hostgroups)) {
  2278. delete $Global::host{$string};
  2279. }
  2280. }
  2281. }
  2282. # debug("start", "sshlogin: ", my_dump(%Global::host),"\n");
  2283. if($opt::transfer or @opt::return or $opt::cleanup or @opt::basefile) {
  2284. if(not remote_hosts()) {
  2285. # There are no remote hosts
  2286. if(@opt::trc) {
  2287. ::warning("--trc ignored as there are no remote --sshlogin.\n");
  2288. } elsif (defined $opt::transfer) {
  2289. ::warning("--transfer ignored as there are no remote --sshlogin.\n");
  2290. } elsif (@opt::return) {
  2291. ::warning("--return ignored as there are no remote --sshlogin.\n");
  2292. } elsif (defined $opt::cleanup) {
  2293. ::warning("--cleanup ignored as there are no remote --sshlogin.\n");
  2294. } elsif (@opt::basefile) {
  2295. ::warning("--basefile ignored as there are no remote --sshlogin.\n");
  2296. }
  2297. }
  2298. }
  2299. }
  2300. sub remote_hosts {
  2301. # Return sshlogins that are not ':'
  2302. # Returns:
  2303. # list of sshlogins with ':' removed
  2304. return grep !/^:$/, keys %Global::host;
  2305. }
  2306. sub setup_basefile {
  2307. # Transfer basefiles to each $sshlogin
  2308. # This needs to be done before first jobs on $sshlogin is run
  2309. # Returns: N/A
  2310. my $cmd = "";
  2311. my $rsync_destdir;
  2312. my $workdir;
  2313. for my $sshlogin (values %Global::host) {
  2314. if($sshlogin->string() eq ":") { next }
  2315. for my $file (@opt::basefile) {
  2316. if($file !~ m:^/: and $opt::workdir eq "...") {
  2317. ::error("Work dir '...' will not work with relative basefiles\n");
  2318. ::wait_and_exit(255);
  2319. }
  2320. $workdir ||= Job->new("")->workdir();
  2321. $cmd .= $sshlogin->rsync_transfer_cmd($file,$workdir) . "&";
  2322. }
  2323. }
  2324. $cmd .= "wait;";
  2325. debug("init", "basesetup: $cmd\n");
  2326. print `$cmd`;
  2327. }
  2328. sub cleanup_basefile {
  2329. # Remove the basefiles transferred
  2330. # Returns: N/A
  2331. my $cmd="";
  2332. my $workdir = Job->new("")->workdir();
  2333. for my $sshlogin (values %Global::host) {
  2334. if($sshlogin->string() eq ":") { next }
  2335. for my $file (@opt::basefile) {
  2336. $cmd .= $sshlogin->cleanup_cmd($file,$workdir)."&";
  2337. }
  2338. }
  2339. $cmd .= "wait;";
  2340. debug("init", "basecleanup: $cmd\n");
  2341. print `$cmd`;
  2342. }
  2343. sub filter_hosts {
  2344. my(@cores, @cpus, @maxline, @echo);
  2345. my $envvar = ::shell_quote_scalar($Global::envvar);
  2346. while (my ($host, $sshlogin) = each %Global::host) {
  2347. if($host eq ":") { next }
  2348. # The 'true' is used to get the $host out later
  2349. my $sshcmd = "true $host;" . $sshlogin->sshcommand()." ".$sshlogin->serverlogin();
  2350. push(@cores, $host."\t".$sshcmd." ".$envvar." parallel --number-of-cores\n\0");
  2351. push(@cpus, $host."\t".$sshcmd." ".$envvar." parallel --number-of-cpus\n\0");
  2352. push(@maxline, $host."\t".$sshcmd." ".$envvar." parallel --max-line-length-allowed\n\0");
  2353. # 'echo' is used to get the best possible value for an ssh login time
  2354. push(@echo, $host."\t".$sshcmd." echo\n\0");
  2355. }
  2356. my ($fh, $tmpfile) = ::tmpfile(SUFFIX => ".ssh");
  2357. print $fh @cores, @cpus, @maxline, @echo;
  2358. close $fh;
  2359. # --timeout 5: Setting up an SSH connection and running a simple
  2360. # command should never take > 5 sec.
  2361. # --delay 0.1: If multiple sshlogins use the same proxy the delay
  2362. # will make it less likely to overload the ssh daemon.
  2363. # --retries 3: If the ssh daemon it overloaded, try 3 times
  2364. # -s 16000: Half of the max line on UnixWare
  2365. my $cmd = "cat $tmpfile | $0 -j0 --timeout 5 -s 16000 --joblog - --plain --delay 0.1 --retries 3 --tag --tagstring {1} -0 --colsep '\t' -k eval {2} 2>/dev/null";
  2366. ::debug("init", $cmd, "\n");
  2367. open(my $host_fh, "-|", $cmd) || ::die_bug("parallel host check: $cmd");
  2368. my (%ncores, %ncpus, %time_to_login, %maxlen, %echo, @down_hosts);
  2369. my $prepend = "";
  2370. while(<$host_fh>) {
  2371. if(/\'$/) {
  2372. # if last char = ' then append next line
  2373. # This may be due to quoting of $Global::envvar
  2374. $prepend .= $_;
  2375. next;
  2376. }
  2377. $_ = $prepend . $_;
  2378. $prepend = "";
  2379. chomp;
  2380. my @col = split /\t/, $_;
  2381. if(defined $col[6]) {
  2382. # This is a line from --joblog
  2383. # seq host time spent sent received exit signal command
  2384. # 2 : 1372607672.654 0.675 0 0 0 0 eval true\ m\;ssh\ m\ parallel\ --number-of-cores
  2385. if($col[0] eq "Seq" and $col[1] eq "Host" and
  2386. $col[2] eq "Starttime") {
  2387. # Header => skip
  2388. next;
  2389. }
  2390. # Get server from: eval true server\;
  2391. $col[8] =~ /eval true..([^;]+).;/ or ::die_bug("col8 does not contain host: $col[8]");
  2392. my $host = $1;
  2393. $host =~ tr/\\//d;
  2394. $Global::host{$host} or next;
  2395. if($col[6] eq "255" or $col[7] eq "15") {
  2396. # exit == 255 or signal == 15: ssh failed
  2397. # Remove sshlogin
  2398. ::debug("init", "--filtered $host\n");
  2399. push(@down_hosts, $host);
  2400. @down_hosts = uniq(@down_hosts);
  2401. } elsif($col[6] eq "127") {
  2402. # signal == 127: parallel not installed remote
  2403. # Set ncpus and ncores = 1
  2404. ::warning("Could not figure out ",
  2405. "number of cpus on $host. Using 1.\n");
  2406. $ncores{$host} = 1;
  2407. $ncpus{$host} = 1;
  2408. $maxlen{$host} = Limits::Command::max_length();
  2409. } elsif($col[0] =~ /^\d+$/ and $Global::host{$host}) {
  2410. # Remember how log it took to log in
  2411. # 2 : 1372607672.654 0.675 0 0 0 0 eval true\ m\;ssh\ m\ echo
  2412. $time_to_login{$host} = ::min($time_to_login{$host},$col[3]);
  2413. } else {
  2414. ::die_bug("host check unmatched long jobline: $_");
  2415. }
  2416. } elsif($Global::host{$col[0]}) {
  2417. # This output from --number-of-cores, --number-of-cpus,
  2418. # --max-line-length-allowed
  2419. # ncores: server 8
  2420. # ncpus: server 2
  2421. # maxlen: server 131071
  2422. if(not $ncores{$col[0]}) {
  2423. $ncores{$col[0]} = $col[1];
  2424. } elsif(not $ncpus{$col[0]}) {
  2425. $ncpus{$col[0]} = $col[1];
  2426. } elsif(not $maxlen{$col[0]}) {
  2427. $maxlen{$col[0]} = $col[1];
  2428. } elsif(not $echo{$col[0]}) {
  2429. $echo{$col[0]} = $col[1];
  2430. } elsif(m/perl: warning:|LANGUAGE =|LC_ALL =|LANG =|are supported and installed/) {
  2431. # Skip these:
  2432. # perl: warning: Setting locale failed.
  2433. # perl: warning: Please check that your locale settings:
  2434. # LANGUAGE = (unset),
  2435. # LC_ALL = (unset),
  2436. # LANG = "en_US.UTF-8"
  2437. # are supported and installed on your system.
  2438. # perl: warning: Falling back to the standard locale ("C").
  2439. } else {
  2440. ::die_bug("host check too many col0: $_");
  2441. }
  2442. } else {
  2443. ::die_bug("host check unmatched short jobline ($col[0]): $_");
  2444. }
  2445. }
  2446. close $host_fh;
  2447. $Global::debug or unlink $tmpfile;
  2448. delete @Global::host{@down_hosts};
  2449. @down_hosts and ::warning("Removed @down_hosts\n");
  2450. $Global::minimal_command_line_length = 8_000_000;
  2451. while (my ($sshlogin, $obj) = each %Global::host) {
  2452. if($sshlogin eq ":") { next }
  2453. $ncpus{$sshlogin} or ::die_bug("ncpus missing: ".$obj->serverlogin());
  2454. $ncores{$sshlogin} or ::die_bug("ncores missing: ".$obj->serverlogin());
  2455. $time_to_login{$sshlogin} or ::die_bug("time_to_login missing: ".$obj->serverlogin());
  2456. $maxlen{$sshlogin} or ::die_bug("maxlen missing: ".$obj->serverlogin());
  2457. if($opt::use_cpus_instead_of_cores) {
  2458. $obj->set_ncpus($ncpus{$sshlogin});
  2459. } else {
  2460. $obj->set_ncpus($ncores{$sshlogin});
  2461. }
  2462. $obj->set_time_to_login($time_to_login{$sshlogin});
  2463. $obj->set_maxlength($maxlen{$sshlogin});
  2464. $Global::minimal_command_line_length =
  2465. ::min($Global::minimal_command_line_length,
  2466. int($maxlen{$sshlogin}/2));
  2467. ::debug("init", "Timing from -S:$sshlogin ncpus:",$ncpus{$sshlogin},
  2468. " ncores:", $ncores{$sshlogin},
  2469. " time_to_login:", $time_to_login{$sshlogin},
  2470. " maxlen:", $maxlen{$sshlogin},
  2471. " min_max_len:", $Global::minimal_command_line_length,"\n");
  2472. }
  2473. }
  2474. sub onall {
  2475. sub tmp_joblog {
  2476. my $joblog = shift;
  2477. if(not defined $joblog) {
  2478. return undef;
  2479. }
  2480. my ($fh, $tmpfile) = ::tmpfile(SUFFIX => ".log");
  2481. close $fh;
  2482. return $tmpfile;
  2483. }
  2484. my @command = @_;
  2485. if($Global::quoting) {
  2486. @command = shell_quote_empty(@command);
  2487. }
  2488. # Copy all @fhlist into tempfiles
  2489. my @argfiles = ();
  2490. for my $fh (@fhlist) {
  2491. my ($outfh, $name) = ::tmpfile(SUFFIX => ".all", UNLINK => 1);
  2492. print $outfh (<$fh>);
  2493. close $outfh;
  2494. push @argfiles, $name;
  2495. }
  2496. if(@opt::basefile) { setup_basefile(); }
  2497. # for each sshlogin do:
  2498. # parallel -S $sshlogin $command :::: @argfiles
  2499. #
  2500. # Pass some of the options to the sub-parallels, not all of them as
  2501. # -P should only go to the first, and -S should not be copied at all.
  2502. my $options =
  2503. join(" ",
  2504. ((defined $opt::jobs) ? "-P $opt::jobs" : ""),
  2505. ((defined $opt::linebuffer) ? "--linebuffer" : ""),
  2506. ((defined $opt::ungroup) ? "-u" : ""),
  2507. ((defined $opt::group) ? "-g" : ""),
  2508. ((defined $opt::keeporder) ? "--keeporder" : ""),
  2509. ((defined $opt::D) ? "-D $opt::D" : ""),
  2510. ((defined $opt::plain) ? "--plain" : ""),
  2511. ((defined $opt::max_chars) ? "--max-chars ".$opt::max_chars : ""),
  2512. );
  2513. my $suboptions =
  2514. join(" ",
  2515. ((defined $opt::ungroup) ? "-u" : ""),
  2516. ((defined $opt::linebuffer) ? "--linebuffer" : ""),
  2517. ((defined $opt::group) ? "-g" : ""),
  2518. ((defined $opt::files) ? "--files" : ""),
  2519. ((defined $opt::keeporder) ? "--keeporder" : ""),
  2520. ((defined $opt::colsep) ? "--colsep ".shell_quote($opt::colsep) : ""),
  2521. ((@opt::v) ? "-vv" : ""),
  2522. ((defined $opt::D) ? "-D $opt::D" : ""),
  2523. ((defined $opt::timeout) ? "--timeout ".$opt::timeout : ""),
  2524. ((defined $opt::plain) ? "--plain" : ""),
  2525. ((defined $opt::retries) ? "--retries ".$opt::retries : ""),
  2526. ((defined $opt::max_chars) ? "--max-chars ".$opt::max_chars : ""),
  2527. ((defined $opt::arg_sep) ? "--arg-sep ".$opt::arg_sep : ""),
  2528. ((defined $opt::arg_file_sep) ? "--arg-file-sep ".$opt::arg_file_sep : ""),
  2529. (@opt::env ? map { "--env ".::shell_quote_scalar($_) } @opt::env : ""),
  2530. );
  2531. ::debug("init", "| $0 $options\n");
  2532. open(my $parallel_fh, "|-", "$0 --no-notice -j0 $options") ||
  2533. ::die_bug("This does not run GNU Parallel: $0 $options");
  2534. my @joblogs;
  2535. for my $host (sort keys %Global::host) {
  2536. my $sshlogin = $Global::host{$host};
  2537. my $joblog = tmp_joblog($opt::joblog);
  2538. if($joblog) {
  2539. push @joblogs, $joblog;
  2540. $joblog = "--joblog $joblog";
  2541. }
  2542. my $quad = $opt::arg_file_sep || "::::";
  2543. ::debug("init", "$0 $suboptions -j1 $joblog ",
  2544. ((defined $opt::tag) ?
  2545. "--tagstring ".shell_quote_scalar($sshlogin->string()) : ""),
  2546. " -S ", shell_quote_scalar($sshlogin->string())," ",
  2547. join(" ",shell_quote(@command))," $quad @argfiles\n");
  2548. print $parallel_fh "$0 $suboptions -j1 $joblog ",
  2549. ((defined $opt::tag) ?
  2550. "--tagstring ".shell_quote_scalar($sshlogin->string()) : ""),
  2551. " -S ", shell_quote_scalar($sshlogin->string())," ",
  2552. join(" ",shell_quote(@command))," $quad @argfiles\n";
  2553. }
  2554. close $parallel_fh;
  2555. $Global::exitstatus = $? >> 8;
  2556. debug("init", "--onall exitvalue ", $?);
  2557. if(@opt::basefile) { cleanup_basefile(); }
  2558. $Global::debug or unlink(@argfiles);
  2559. my %seen;
  2560. for my $joblog (@joblogs) {
  2561. # Append to $joblog
  2562. open(my $fh, "<", $joblog) || ::die_bug("Cannot open tmp joblog $joblog");
  2563. # Skip first line (header);
  2564. <$fh>;
  2565. print $Global::joblog (<$fh>);
  2566. close $fh;
  2567. unlink($joblog);
  2568. }
  2569. }
  2570. sub __SIGNAL_HANDLING__ {}
  2571. sub save_original_signal_handler {
  2572. # Remember the original signal handler
  2573. # Returns: N/A
  2574. $SIG{TERM} ||= sub { exit 0; }; # $SIG{TERM} is not set on Mac OS X
  2575. $SIG{INT} = sub { if($opt::tmux) { qx { tmux kill-session -t p$$ }; }
  2576. unlink keys %Global::unlink; exit -1 };
  2577. $SIG{TERM} = sub { if($opt::tmux) { qx { tmux kill-session -t p$$ }; }
  2578. unlink keys %Global::unlink; exit -1 };
  2579. %Global::original_sig = %SIG;
  2580. $SIG{TERM} = sub {}; # Dummy until jobs really start
  2581. }
  2582. sub list_running_jobs {
  2583. # Returns: N/A
  2584. for my $v (values %Global::running) {
  2585. print $Global::original_stderr "$Global::progname: ",$v->replaced(),"\n";
  2586. }
  2587. }
  2588. sub start_no_new_jobs {
  2589. # Returns: N/A
  2590. $SIG{TERM} = $Global::original_sig{TERM};
  2591. print $Global::original_stderr
  2592. ("$Global::progname: SIGTERM received. No new jobs will be started.\n",
  2593. "$Global::progname: Waiting for these ", scalar(keys %Global::running),
  2594. " jobs to finish. Send SIGTERM again to stop now.\n");
  2595. list_running_jobs();
  2596. $Global::start_no_new_jobs ||= 1;
  2597. }
  2598. sub reaper {
  2599. # A job finished.
  2600. # Print the output.
  2601. # Start another job
  2602. # Returns: N/A
  2603. my $stiff;
  2604. my $children_reaped = 0;
  2605. debug("run", "Reaper ");
  2606. while (($stiff = waitpid(-1, &WNOHANG)) > 0) {
  2607. $children_reaped++;
  2608. if($Global::sshmaster{$stiff}) {
  2609. # This is one of the ssh -M: ignore
  2610. next;
  2611. }
  2612. my $job = $Global::running{$stiff};
  2613. # '-a <(seq 10)' will give us a pid not in %Global::running
  2614. $job or next;
  2615. $job->set_exitstatus($? >> 8);
  2616. $job->set_exitsignal($? & 127);
  2617. debug("run", "died (", $job->exitstatus(), "): ", $job->seq());
  2618. $job->set_endtime(::now());
  2619. if($stiff == $Global::tty_taken) {
  2620. # The process that died had the tty => release it
  2621. $Global::tty_taken = 0;
  2622. }
  2623. if(not $job->should_be_retried()) {
  2624. # The job is done
  2625. # Free the jobslot
  2626. push @Global::slots, $job->slot();
  2627. if($opt::timeout) {
  2628. # Update average runtime for timeout
  2629. $Global::timeoutq->update_delta_time($job->runtime());
  2630. }
  2631. # Force printing now if the job failed and we are going to exit
  2632. my $print_now = ($opt::halt_on_error and $opt::halt_on_error == 2
  2633. and $job->exitstatus());
  2634. if($opt::keeporder and not $print_now) {
  2635. print_earlier_jobs($job);
  2636. } else {
  2637. $job->print();
  2638. }
  2639. if($job->exitstatus()) {
  2640. process_failed_job($job);
  2641. }
  2642. }
  2643. my $sshlogin = $job->sshlogin();
  2644. $sshlogin->dec_jobs_running();
  2645. $sshlogin->inc_jobs_completed();
  2646. $Global::total_running--;
  2647. delete $Global::running{$stiff};
  2648. start_more_jobs();
  2649. }
  2650. debug("run", "done ");
  2651. return $children_reaped;
  2652. }
  2653. sub process_failed_job {
  2654. # The jobs had a exit status <> 0, so error
  2655. # Returns: N/A
  2656. my $job = shift;
  2657. $Global::exitstatus++;
  2658. $Global::total_failed++;
  2659. if($opt::halt_on_error) {
  2660. if($opt::halt_on_error == 1
  2661. or
  2662. ($opt::halt_on_error < 1 and $Global::total_failed > 3
  2663. and
  2664. $Global::total_failed / $Global::total_started > $opt::halt_on_error)) {
  2665. # If halt on error == 1 or --halt 10%
  2666. # we should gracefully exit
  2667. print $Global::original_stderr
  2668. ("$Global::progname: Starting no more jobs. ",
  2669. "Waiting for ", scalar(keys %Global::running),
  2670. " jobs to finish. This job failed:\n",
  2671. $job->replaced(),"\n");
  2672. $Global::start_no_new_jobs ||= 1;
  2673. $Global::halt_on_error_exitstatus = $job->exitstatus();
  2674. } elsif($opt::halt_on_error == 2) {
  2675. # If halt on error == 2 we should exit immediately
  2676. print $Global::original_stderr
  2677. ("$Global::progname: This job failed:\n",
  2678. $job->replaced(),"\n");
  2679. exit ($job->exitstatus());
  2680. }
  2681. }
  2682. }
  2683. {
  2684. my (%print_later,$job_end_sequence);
  2685. sub print_earlier_jobs {
  2686. # Print jobs completed earlier
  2687. # Returns: N/A
  2688. my $job = shift;
  2689. $print_later{$job->seq()} = $job;
  2690. $job_end_sequence ||= 1;
  2691. debug("run", "Looking for: $job_end_sequence ",
  2692. "Current: ", $job->seq(), "\n");
  2693. for(my $j = $print_later{$job_end_sequence};
  2694. $j or vec($Global::job_already_run,$job_end_sequence,1);
  2695. $job_end_sequence++,
  2696. $j = $print_later{$job_end_sequence}) {
  2697. debug("run", "Found job end $job_end_sequence");
  2698. if($j) {
  2699. $j->print();
  2700. delete $print_later{$job_end_sequence};
  2701. }
  2702. }
  2703. }
  2704. }
  2705. sub __USAGE__ {}
  2706. sub wait_and_exit {
  2707. # If we do not wait, we sometimes get segfault
  2708. # Returns: N/A
  2709. my $error = shift;
  2710. if($error) {
  2711. # Kill all without printing
  2712. for my $job (values %Global::running) {
  2713. $job->kill("TERM");
  2714. $job->kill("TERM");
  2715. }
  2716. }
  2717. for (keys %Global::unkilled_children) {
  2718. kill 9, $_;
  2719. waitpid($_,0);
  2720. delete $Global::unkilled_children{$_};
  2721. }
  2722. wait();
  2723. exit($error);
  2724. }
  2725. sub die_usage {
  2726. # Returns: N/A
  2727. usage();
  2728. wait_and_exit(255);
  2729. }
  2730. sub usage {
  2731. # Returns: N/A
  2732. print join
  2733. ("\n",
  2734. "Usage:",
  2735. "",
  2736. "$Global::progname [options] [command [arguments]] < list_of_arguments",
  2737. "$Global::progname [options] [command [arguments]] (::: arguments|:::: argfile(s))...",
  2738. "cat ... | $Global::progname --pipe [options] [command [arguments]]",
  2739. "",
  2740. "-j n Run n jobs in parallel",
  2741. "-k Keep same order",
  2742. "-X Multiple arguments with context replace",
  2743. "--colsep regexp Split input on regexp for positional replacements",
  2744. "{} {.} {/} {/.} {#} {%} {= perl code =} Replacement strings",
  2745. "{3} {3.} {3/} {3/.} {=3 perl code =} Positional replacement strings",
  2746. "With --plus: {} = {+/}/{/} = {.}.{+.} = {+/}/{/.}.{+.} = {..}.{+..} =",
  2747. " {+/}/{/..}.{+..} = {...}.{+...} = {+/}/{/...}.{+...}",
  2748. "",
  2749. "-S sshlogin Example: foo\@server.example.com",
  2750. "--slf .. Use ~/.parallel/sshloginfile as the list of sshlogins",
  2751. "--trc {}.bar Shorthand for --transfer --return {}.bar --cleanup",
  2752. "--onall Run the given command with argument on all sshlogins",
  2753. "--nonall Run the given command with no arguments on all sshlogins",
  2754. "",
  2755. "--pipe Split stdin (standard input) to multiple jobs.",
  2756. "--recend str Record end separator for --pipe.",
  2757. "--recstart str Record start separator for --pipe.",
  2758. "",
  2759. "See 'man $Global::progname' for details",
  2760. "",
  2761. "When using programs that use GNU Parallel to process data for publication please cite:",
  2762. "",
  2763. "O. Tange (2011): GNU Parallel - The Command-Line Power Tool,",
  2764. ";login: The USENIX Magazine, February 2011:42-47.",
  2765. "",
  2766. "Or you can get GNU Parallel without this requirement by paying 10000 EUR.",
  2767. "");
  2768. }
  2769. sub citation_notice {
  2770. # if --no-notice or --plain: do nothing
  2771. # if stderr redirected: do nothing
  2772. # if ~/.parallel/will-cite: do nothing
  2773. # else: print citation notice to stderr
  2774. if($opt::no_notice
  2775. or
  2776. $opt::plain
  2777. or
  2778. not -t $Global::original_stderr
  2779. or
  2780. -e $ENV{'HOME'}."/.parallel/will-cite") {
  2781. # skip
  2782. } else {
  2783. print $Global::original_stderr
  2784. ("When using programs that use GNU Parallel to process data for publication please cite:\n",
  2785. "\n",
  2786. " O. Tange (2011): GNU Parallel - The Command-Line Power Tool,\n",
  2787. " ;login: The USENIX Magazine, February 2011:42-47.\n",
  2788. "\n",
  2789. "This helps funding further development; and it won't cost you a cent.\n",
  2790. "Or you can get GNU Parallel without this requirement by paying 10000 EUR.\n",
  2791. "\n",
  2792. "To silence this citation notice run 'parallel --bibtex' once or use '--no-notice'.\n\n",
  2793. );
  2794. flush $Global::original_stderr;
  2795. }
  2796. }
  2797. sub warning {
  2798. my @w = @_;
  2799. my $fh = $Global::original_stderr || *STDERR;
  2800. my $prog = $Global::progname || "parallel";
  2801. print $fh $prog, ": Warning: ", @w;
  2802. }
  2803. sub error {
  2804. my @w = @_;
  2805. my $fh = $Global::original_stderr || *STDERR;
  2806. my $prog = $Global::progname || "parallel";
  2807. print $fh $prog, ": Error: ", @w;
  2808. }
  2809. sub die_bug {
  2810. my $bugid = shift;
  2811. print STDERR
  2812. ("$Global::progname: This should not happen. You have found a bug.\n",
  2813. "Please contact <parallel\@gnu.org> and include:\n",
  2814. "* The version number: $Global::version\n",
  2815. "* The bugid: $bugid\n",
  2816. "* The command line being run\n",
  2817. "* The files being read (put the files on a webserver if they are big)\n",
  2818. "\n",
  2819. "If you get the error on smaller/fewer files, please include those instead.\n");
  2820. ::wait_and_exit(255);
  2821. }
  2822. sub version {
  2823. # Returns: N/A
  2824. if($opt::tollef and not $opt::gnu) {
  2825. print "WARNING: YOU ARE USING --tollef. IF THINGS ARE ACTING WEIRD USE --gnu.\n";
  2826. }
  2827. print join("\n",
  2828. "GNU $Global::progname $Global::version",
  2829. "Copyright (C) 2007,2008,2009,2010,2011,2012,2013,2014 Ole Tange and Free Software Foundation, Inc.",
  2830. "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>",
  2831. "This is free software: you are free to change and redistribute it.",
  2832. "GNU $Global::progname comes with no warranty.",
  2833. "",
  2834. "Web site: http://www.gnu.org/software/${Global::progname}\n",
  2835. "When using programs that use GNU Parallel to process data for publication please cite:\n",
  2836. "O. Tange (2011): GNU Parallel - The Command-Line Power Tool, ",
  2837. ";login: The USENIX Magazine, February 2011:42-47.\n",
  2838. "Or you can get GNU Parallel without this requirement by paying 10000 EUR.\n",
  2839. );
  2840. }
  2841. sub bibtex {
  2842. # Returns: N/A
  2843. if($opt::tollef and not $opt::gnu) {
  2844. print "WARNING: YOU ARE USING --tollef. IF THINGS ARE ACTING WEIRD USE --gnu.\n";
  2845. }
  2846. print join("\n",
  2847. "When using programs that use GNU Parallel to process data for publication please cite:",
  2848. "",
  2849. "\@article{Tange2011a,",
  2850. " title = {GNU Parallel - The Command-Line Power Tool},",
  2851. " author = {O. Tange},",
  2852. " address = {Frederiksberg, Denmark},",
  2853. " journal = {;login: The USENIX Magazine},",
  2854. " month = {Feb},",
  2855. " number = {1},",
  2856. " volume = {36},",
  2857. " url = {http://www.gnu.org/s/parallel},",
  2858. " year = {2011},",
  2859. " pages = {42-47}",
  2860. "}",
  2861. "",
  2862. "(Feel free to use \\nocite{Tange2011a})",
  2863. "",
  2864. "This helps funding further development.",
  2865. "",
  2866. "Or you can get GNU Parallel without this requirement by paying 10000 EUR.",
  2867. ""
  2868. );
  2869. while(not -e $ENV{'HOME'}."/.parallel/will-cite") {
  2870. print "\nType: 'will cite' and press enter.\n> ";
  2871. my $input = <STDIN>;
  2872. if($input =~ /will cite/i) {
  2873. mkdir $ENV{'HOME'}."/.parallel";
  2874. open (my $fh, ">", $ENV{'HOME'}."/.parallel/will-cite")
  2875. || ::die_bug("Cannot write: ".$ENV{'HOME'}."/.parallel/will-cite");
  2876. close $fh;
  2877. print "\nThank you for your support. It is much appreciated. The citation\n",
  2878. "notice is now silenced.\n";
  2879. }
  2880. }
  2881. }
  2882. sub show_limits {
  2883. # Returns: N/A
  2884. print("Maximal size of command: ",Limits::Command::real_max_length(),"\n",
  2885. "Maximal used size of command: ",Limits::Command::max_length(),"\n",
  2886. "\n",
  2887. "Execution of will continue now, and it will try to read its input\n",
  2888. "and run commands; if this is not what you wanted to happen, please\n",
  2889. "press CTRL-D or CTRL-C\n");
  2890. }
  2891. sub __GENERIC_COMMON_FUNCTION__ {}
  2892. sub uniq {
  2893. # Remove duplicates and return unique values
  2894. return keys %{{ map { $_ => 1 } @_ }};
  2895. }
  2896. sub min {
  2897. # Returns:
  2898. # Minimum value of array
  2899. my $min;
  2900. for (@_) {
  2901. # Skip undefs
  2902. defined $_ or next;
  2903. defined $min or do { $min = $_; next; }; # Set $_ to the first non-undef
  2904. $min = ($min < $_) ? $min : $_;
  2905. }
  2906. return $min;
  2907. }
  2908. sub max {
  2909. # Returns:
  2910. # Maximum value of array
  2911. my $max;
  2912. for (@_) {
  2913. # Skip undefs
  2914. defined $_ or next;
  2915. defined $max or do { $max = $_; next; }; # Set $_ to the first non-undef
  2916. $max = ($max > $_) ? $max : $_;
  2917. }
  2918. return $max;
  2919. }
  2920. sub sum {
  2921. # Returns:
  2922. # Sum of values of array
  2923. my @args = @_;
  2924. my $sum = 0;
  2925. for (@args) {
  2926. # Skip undefs
  2927. $_ and do { $sum += $_; }
  2928. }
  2929. return $sum;
  2930. }
  2931. sub undef_as_zero {
  2932. my $a = shift;
  2933. return $a ? $a : 0;
  2934. }
  2935. sub undef_as_empty {
  2936. my $a = shift;
  2937. return $a ? $a : "";
  2938. }
  2939. {
  2940. my $hostname;
  2941. sub hostname {
  2942. if(not $hostname) {
  2943. $hostname = `hostname`;
  2944. chomp($hostname);
  2945. $hostname ||= "nohostname";
  2946. }
  2947. return $hostname;
  2948. }
  2949. }
  2950. sub which {
  2951. # Input:
  2952. # @programs = programs to find the path to
  2953. # Returns:
  2954. # @full_path = full paths to @programs. Nothing if not found
  2955. my @which;
  2956. for my $prg (@_) {
  2957. push @which, map { $_."/".$prg } grep { -x $_."/".$prg } split(":",$ENV{'PATH'});
  2958. }
  2959. return @which;
  2960. }
  2961. {
  2962. my ($regexp,%fakename);
  2963. sub parent_shell {
  2964. # Input:
  2965. # $pid = pid to see if (grand)*parent is a shell
  2966. # Returns:
  2967. # $shellpath = path to shell - undef if no shell found
  2968. my $pid = shift;
  2969. if(not $regexp) {
  2970. # All shells known to mankind
  2971. #
  2972. # ash bash csh dash fdsh fish fizsh ksh ksh93 mksh pdksh
  2973. # posh rbash rush rzsh sash sh static-sh tcsh yash zsh
  2974. my @shells = qw(ash bash csh dash fdsh fish fizsh ksh
  2975. ksh93 mksh pdksh posh rbash rush rzsh
  2976. sash sh static-sh tcsh yash zsh -sh -csh);
  2977. # Can be formatted as:
  2978. # [sh] -sh sh busybox sh
  2979. # /bin/sh /sbin/sh /opt/csw/sh
  2980. # NOT: foo.sh sshd crash flush pdflush scosh fsflush ssh
  2981. my $shell = "(?:".join("|",@shells).")";
  2982. $regexp = '^((\[)('. $shell. ')(\])|(|\S+/|busybox )('. $shell. '))($| )';
  2983. %fakename = (
  2984. # csh and tcsh disguise themselves as -sh/-csh
  2985. "-sh" => ["csh", "tcsh"],
  2986. "-csh" => ["tcsh", "csh"],
  2987. );
  2988. }
  2989. my ($children_of_ref, $parent_of_ref, $name_of_ref) = pid_table();
  2990. my $shellpath;
  2991. my $testpid = $pid;
  2992. while($testpid) {
  2993. ::debug("init", "shell? ". $name_of_ref->{$testpid}."\n");
  2994. if($name_of_ref->{$testpid} =~ /$regexp/o) {
  2995. ::debug("init", "which ".($3||$6)." => ");
  2996. $shellpath = (which($3 || $6,@{$fakename{$3 || $6}}))[0];
  2997. ::debug("init", "shell path $shellpath\n");
  2998. $shellpath and last;
  2999. }
  3000. $testpid = $parent_of_ref->{$testpid};
  3001. }
  3002. return $shellpath;
  3003. }
  3004. }
  3005. {
  3006. my %pid_parentpid_cmd;
  3007. sub pid_table {
  3008. # Returns:
  3009. # %children_of = { pid -> children of pid }
  3010. # %parent_of = { pid -> pid of parent }
  3011. # %name_of = { pid -> commandname }
  3012. if(not %pid_parentpid_cmd) {
  3013. # Filter for SysV-style `ps`
  3014. my $sysv = q( ps -ef | perl -ane '1..1 and /^(.*)CO?MM?A?N?D/ and $s=length $1;).
  3015. q(s/^.{$s}//; print "@F[1,2] $_"' );
  3016. # BSD-style `ps`
  3017. my $bsd = q(ps -o pid,ppid,command -ax);
  3018. %pid_parentpid_cmd =
  3019. (
  3020. 'aix' => $sysv,
  3021. 'cygwin' => $sysv,
  3022. 'msys' => $sysv,
  3023. 'dec_osf' => $sysv,
  3024. 'darwin' => $bsd,
  3025. 'dragonfly' => $bsd,
  3026. 'freebsd' => $bsd,
  3027. 'gnu' => $sysv,
  3028. 'hpux' => $sysv,
  3029. 'linux' => $sysv,
  3030. 'mirbsd' => $bsd,
  3031. 'netbsd' => $bsd,
  3032. 'nto' => $sysv,
  3033. 'openbsd' => $bsd,
  3034. 'solaris' => $sysv,
  3035. 'svr5' => $sysv,
  3036. );
  3037. }
  3038. $pid_parentpid_cmd{$^O} or ::die_bug("pid_parentpid_cmd for $^O missing");
  3039. my (@pidtable,%parent_of,%children_of,%name_of);
  3040. # Table with pid -> children of pid
  3041. @pidtable = `$pid_parentpid_cmd{$^O}`;
  3042. my $p=$$;
  3043. for (@pidtable) {
  3044. # must match: 24436 21224 busybox ash
  3045. /(\S+)\s+(\S+)\s+(\S+.*)/ or ::die_bug("pidtable format: $_");
  3046. $parent_of{$1} = $2;
  3047. push @{$children_of{$2}}, $1;
  3048. $name_of{$1} = $3;
  3049. }
  3050. return(\%children_of, \%parent_of, \%name_of);
  3051. }
  3052. }
  3053. sub reap_usleep {
  3054. # Reap dead children.
  3055. # If no dead children: Sleep specified amount with exponential backoff
  3056. # Input:
  3057. # $ms = milliseconds to sleep
  3058. # Returns:
  3059. # $ms/2+0.001 if children reaped
  3060. # $ms*1.1 if no children reaped
  3061. my $ms = shift;
  3062. if(reaper()) {
  3063. # Sleep exponentially shorter (1/2^n) if a job finished
  3064. return $ms/2+0.001;
  3065. } else {
  3066. if($opt::timeout) {
  3067. $Global::timeoutq->process_timeouts();
  3068. }
  3069. usleep($ms);
  3070. Job::exit_if_disk_full();
  3071. if($opt::linebuffer) {
  3072. for my $job (values %Global::running) {
  3073. $job->print();
  3074. }
  3075. }
  3076. # Sleep exponentially longer (1.1^n) if a job did not finish
  3077. # though at most 1000 ms.
  3078. return (($ms < 1000) ? ($ms * 1.1) : ($ms));
  3079. }
  3080. }
  3081. sub usleep {
  3082. # Sleep this many milliseconds.
  3083. # Input:
  3084. # $ms = milliseconds to sleep
  3085. my $ms = shift;
  3086. ::debug(int($ms),"ms ");
  3087. select(undef, undef, undef, $ms/1000);
  3088. }
  3089. sub now {
  3090. # Returns time since epoch as in seconds with 3 decimals
  3091. # Uses:
  3092. # @Global::use
  3093. # Returns:
  3094. # $time = time now with millisecond accuracy
  3095. if(not $Global::use{"Time::HiRes"}) {
  3096. if(eval "use Time::HiRes qw ( time );") {
  3097. eval "sub TimeHiRestime { return Time::HiRes::time };";
  3098. } else {
  3099. eval "sub TimeHiRestime { return time() };";
  3100. }
  3101. $Global::use{"Time::HiRes"} = 1;
  3102. }
  3103. return (int(TimeHiRestime()*1000))/1000;
  3104. }
  3105. sub multiply_binary_prefix {
  3106. # Evalualte numbers with binary prefix
  3107. # Ki=2^10, Mi=2^20, Gi=2^30, Ti=2^40, Pi=2^50, Ei=2^70, Zi=2^80, Yi=2^80
  3108. # ki=2^10, mi=2^20, gi=2^30, ti=2^40, pi=2^50, ei=2^70, zi=2^80, yi=2^80
  3109. # K =2^10, M =2^20, G =2^30, T =2^40, P =2^50, E =2^70, Z =2^80, Y =2^80
  3110. # k =10^3, m =10^6, g =10^9, t=10^12, p=10^15, e=10^18, z=10^21, y=10^24
  3111. # 13G = 13*1024*1024*1024 = 13958643712
  3112. # Input:
  3113. # $s = string with prefixes
  3114. # Returns:
  3115. # $value = int with prefixes multiplied
  3116. my $s = shift;
  3117. $s =~ s/ki/*1024/gi;
  3118. $s =~ s/mi/*1024*1024/gi;
  3119. $s =~ s/gi/*1024*1024*1024/gi;
  3120. $s =~ s/ti/*1024*1024*1024*1024/gi;
  3121. $s =~ s/pi/*1024*1024*1024*1024*1024/gi;
  3122. $s =~ s/ei/*1024*1024*1024*1024*1024*1024/gi;
  3123. $s =~ s/zi/*1024*1024*1024*1024*1024*1024*1024/gi;
  3124. $s =~ s/yi/*1024*1024*1024*1024*1024*1024*1024*1024/gi;
  3125. $s =~ s/xi/*1024*1024*1024*1024*1024*1024*1024*1024*1024/gi;
  3126. $s =~ s/K/*1024/g;
  3127. $s =~ s/M/*1024*1024/g;
  3128. $s =~ s/G/*1024*1024*1024/g;
  3129. $s =~ s/T/*1024*1024*1024*1024/g;
  3130. $s =~ s/P/*1024*1024*1024*1024*1024/g;
  3131. $s =~ s/E/*1024*1024*1024*1024*1024*1024/g;
  3132. $s =~ s/Z/*1024*1024*1024*1024*1024*1024*1024/g;
  3133. $s =~ s/Y/*1024*1024*1024*1024*1024*1024*1024*1024/g;
  3134. $s =~ s/X/*1024*1024*1024*1024*1024*1024*1024*1024*1024/g;
  3135. $s =~ s/k/*1000/g;
  3136. $s =~ s/m/*1000*1000/g;
  3137. $s =~ s/g/*1000*1000*1000/g;
  3138. $s =~ s/t/*1000*1000*1000*1000/g;
  3139. $s =~ s/p/*1000*1000*1000*1000*1000/g;
  3140. $s =~ s/e/*1000*1000*1000*1000*1000*1000/g;
  3141. $s =~ s/z/*1000*1000*1000*1000*1000*1000*1000/g;
  3142. $s =~ s/y/*1000*1000*1000*1000*1000*1000*1000*1000/g;
  3143. $s =~ s/x/*1000*1000*1000*1000*1000*1000*1000*1000*1000/g;
  3144. $s = eval $s;
  3145. ::debug($s);
  3146. return $s;
  3147. }
  3148. sub tmpfile {
  3149. # Create tempfile as $TMPDIR/parXXXXX
  3150. # Returns:
  3151. # $filename = file name created
  3152. return ::tempfile(DIR=>$ENV{'TMPDIR'}, TEMPLATE => 'parXXXXX', @_);
  3153. }
  3154. sub __DEBUGGING__ {}
  3155. sub debug {
  3156. # Uses:
  3157. # $Global::debug
  3158. # %Global::fd
  3159. # Returns: N/A
  3160. $Global::debug or return;
  3161. @_ = grep { defined $_ ? $_ : "" } @_;
  3162. if($Global::debug eq "all" or $Global::debug eq $_[0]) {
  3163. if($Global::fd{1}) {
  3164. # Original stdout was saved
  3165. my $stdout = $Global::fd{1};
  3166. print $stdout @_[1..$#_];
  3167. } else {
  3168. print @_[1..$#_];
  3169. }
  3170. }
  3171. }
  3172. sub my_memory_usage {
  3173. # Returns:
  3174. # memory usage if found
  3175. # 0 otherwise
  3176. use strict;
  3177. use FileHandle;
  3178. my $pid = $$;
  3179. if(-e "/proc/$pid/stat") {
  3180. my $fh = FileHandle->new("</proc/$pid/stat");
  3181. my $data = <$fh>;
  3182. chomp $data;
  3183. $fh->close;
  3184. my @procinfo = split(/\s+/,$data);
  3185. return undef_as_zero($procinfo[22]);
  3186. } else {
  3187. return 0;
  3188. }
  3189. }
  3190. sub my_size {
  3191. # Returns:
  3192. # $size = size of object if Devel::Size is installed
  3193. # -1 otherwise
  3194. my @size_this = (@_);
  3195. eval "use Devel::Size qw(size total_size)";
  3196. if ($@) {
  3197. return -1;
  3198. } else {
  3199. return total_size(@_);
  3200. }
  3201. }
  3202. sub my_dump {
  3203. # Returns:
  3204. # ascii expression of object if Data::Dump(er) is installed
  3205. # error code otherwise
  3206. my @dump_this = (@_);
  3207. eval "use Data::Dump qw(dump);";
  3208. if ($@) {
  3209. # Data::Dump not installed
  3210. eval "use Data::Dumper;";
  3211. if ($@) {
  3212. my $err = "Neither Data::Dump nor Data::Dumper is installed\n".
  3213. "Not dumping output\n";
  3214. print $Global::original_stderr $err;
  3215. return $err;
  3216. } else {
  3217. return Dumper(@dump_this);
  3218. }
  3219. } else {
  3220. # Create a dummy Data::Dump:dump as Hans Schou sometimes has
  3221. # it undefined
  3222. eval "sub Data::Dump:dump {}";
  3223. eval "use Data::Dump qw(dump);";
  3224. return (Data::Dump::dump(@dump_this));
  3225. }
  3226. }
  3227. sub my_croak {
  3228. eval "use Carp; 1";
  3229. $Carp::Verbose = 1;
  3230. croak(@_);
  3231. }
  3232. sub my_carp {
  3233. eval "use Carp; 1";
  3234. $Carp::Verbose = 1;
  3235. carp(@_);
  3236. }
  3237. sub __OBJECT_ORIENTED_PARTS__ {}
  3238. package SSHLogin;
  3239. sub new {
  3240. my $class = shift;
  3241. my $sshlogin_string = shift;
  3242. my $ncpus;
  3243. my %hostgroups;
  3244. # SSHLogins can have these formats:
  3245. # @grp+grp/ncpu//usr/bin/ssh user@server
  3246. # ncpu//usr/bin/ssh user@server
  3247. # /usr/bin/ssh user@server
  3248. # user@server
  3249. # ncpu/user@server
  3250. # @grp+grp/user@server
  3251. if($sshlogin_string =~ s:^\@([^/]+)/?::) {
  3252. # Look for SSHLogin hostgroups
  3253. %hostgroups = map { $_ => 1 } split(/\+/, $1);
  3254. }
  3255. if ($sshlogin_string =~ s:^(\d+)/::) {
  3256. # Override default autodetected ncpus unless missing
  3257. $ncpus = $1;
  3258. }
  3259. my $string = $sshlogin_string;
  3260. # An SSHLogin is always in the hostgroup of its $string-name
  3261. $hostgroups{$string} = 1;
  3262. @Global::hostgroups{keys %hostgroups} = values %hostgroups;
  3263. my @unget = ();
  3264. my $no_slash_string = $string;
  3265. $no_slash_string =~ s/[^-a-z0-9:]/_/gi;
  3266. return bless {
  3267. 'string' => $string,
  3268. 'jobs_running' => 0,
  3269. 'jobs_completed' => 0,
  3270. 'maxlength' => undef,
  3271. 'max_jobs_running' => undef,
  3272. 'orig_max_jobs_running' => undef,
  3273. 'ncpus' => $ncpus,
  3274. 'hostgroups' => \%hostgroups,
  3275. 'sshcommand' => undef,
  3276. 'serverlogin' => undef,
  3277. 'control_path_dir' => undef,
  3278. 'control_path' => undef,
  3279. 'time_to_login' => undef,
  3280. 'last_login_at' => undef,
  3281. 'loadavg_file' => $ENV{'HOME'} . "/.parallel/tmp/loadavg-" .
  3282. $no_slash_string,
  3283. 'loadavg' => undef,
  3284. 'last_loadavg_update' => 0,
  3285. 'swap_activity_file' => $ENV{'HOME'} . "/.parallel/tmp/swap_activity-" .
  3286. $no_slash_string,
  3287. 'swap_activity' => undef,
  3288. }, ref($class) || $class;
  3289. }
  3290. sub DESTROY {
  3291. my $self = shift;
  3292. # Remove temporary files if they are created.
  3293. unlink $self->{'loadavg_file'};
  3294. unlink $self->{'swap_activity_file'};
  3295. }
  3296. sub string {
  3297. my $self = shift;
  3298. return $self->{'string'};
  3299. }
  3300. sub jobs_running {
  3301. my $self = shift;
  3302. return ($self->{'jobs_running'} || "0");
  3303. }
  3304. sub inc_jobs_running {
  3305. my $self = shift;
  3306. $self->{'jobs_running'}++;
  3307. }
  3308. sub dec_jobs_running {
  3309. my $self = shift;
  3310. $self->{'jobs_running'}--;
  3311. }
  3312. sub set_maxlength {
  3313. my $self = shift;
  3314. $self->{'maxlength'} = shift;
  3315. }
  3316. sub maxlength {
  3317. my $self = shift;
  3318. return $self->{'maxlength'};
  3319. }
  3320. sub jobs_completed {
  3321. my $self = shift;
  3322. return $self->{'jobs_completed'};
  3323. }
  3324. sub in_hostgroups {
  3325. # Input:
  3326. # @hostgroups = the hostgroups to look for
  3327. # Returns:
  3328. # true if intersection of @hostgroups and the hostgroups of this
  3329. # SSHLogin is non-empty
  3330. my $self = shift;
  3331. return grep { defined $self->{'hostgroups'}{$_} } @_;
  3332. }
  3333. sub hostgroups {
  3334. my $self = shift;
  3335. return keys %{$self->{'hostgroups'}};
  3336. }
  3337. sub inc_jobs_completed {
  3338. my $self = shift;
  3339. $self->{'jobs_completed'}++;
  3340. }
  3341. sub set_max_jobs_running {
  3342. my $self = shift;
  3343. if(defined $self->{'max_jobs_running'}) {
  3344. $Global::max_jobs_running -= $self->{'max_jobs_running'};
  3345. }
  3346. $self->{'max_jobs_running'} = shift;
  3347. if(defined $self->{'max_jobs_running'}) {
  3348. # max_jobs_running could be resat if -j is a changed file
  3349. $Global::max_jobs_running += $self->{'max_jobs_running'};
  3350. }
  3351. # Initialize orig to the first non-zero value that comes around
  3352. $self->{'orig_max_jobs_running'} ||= $self->{'max_jobs_running'};
  3353. }
  3354. sub swapping {
  3355. my $self = shift;
  3356. my $swapping = $self->swap_activity();
  3357. return (not defined $swapping or $swapping)
  3358. }
  3359. sub swap_activity {
  3360. # If the currently known swap activity is too old:
  3361. # Recompute a new one in the background
  3362. # Returns:
  3363. # last swap activity computed
  3364. my $self = shift;
  3365. # Should we update the swap_activity file?
  3366. my $update_swap_activity_file = 0;
  3367. if(-r $self->{'swap_activity_file'}) {
  3368. open(my $swap_fh, "<", $self->{'swap_activity_file'}) || ::die_bug("swap_activity_file-r");
  3369. my $swap_out = <$swap_fh>;
  3370. close $swap_fh;
  3371. if($swap_out =~ /^(\d+)$/) {
  3372. $self->{'swap_activity'} = $1;
  3373. ::debug("swap", "New swap_activity: ", $self->{'swap_activity'});
  3374. }
  3375. ::debug("swap", "Last update: ", $self->{'last_swap_activity_update'});
  3376. if(time - $self->{'last_swap_activity_update'} > 10) {
  3377. # last swap activity update was started 10 seconds ago
  3378. ::debug("swap", "Older than 10 sec: ", $self->{'swap_activity_file'});
  3379. $update_swap_activity_file = 1;
  3380. }
  3381. } else {
  3382. ::debug("swap", "No swap_activity file: ", $self->{'swap_activity_file'});
  3383. $self->{'swap_activity'} = undef;
  3384. $update_swap_activity_file = 1;
  3385. }
  3386. if($update_swap_activity_file) {
  3387. ::debug("swap", "Updating swap_activity file ", $self->{'swap_activity_file'});
  3388. $self->{'last_swap_activity_update'} = time;
  3389. -e $ENV{'HOME'}."/.parallel" or mkdir $ENV{'HOME'}."/.parallel";
  3390. -e $ENV{'HOME'}."/.parallel/tmp" or mkdir $ENV{'HOME'}."/.parallel/tmp";
  3391. my $swap_activity;
  3392. $swap_activity = swapactivityscript();
  3393. if($self->{'string'} ne ":") {
  3394. $swap_activity = $self->sshcommand() . " " . $self->serverlogin() . " " .
  3395. ::shell_quote_scalar($swap_activity);
  3396. }
  3397. # Run swap_activity measuring.
  3398. # As the command can take long to run if run remote
  3399. # save it to a tmp file before moving it to the correct file
  3400. my $file = $self->{'swap_activity_file'};
  3401. my ($dummy_fh, $tmpfile) = ::tmpfile(SUFFIX => ".swp");
  3402. ::debug("swap", "\n", $swap_activity, "\n");
  3403. qx{ ($swap_activity > $tmpfile && mv $tmpfile $file || rm $tmpfile) & };
  3404. }
  3405. return $self->{'swap_activity'};
  3406. }
  3407. {
  3408. my $script;
  3409. sub swapactivityscript {
  3410. # Returns:
  3411. # shellscript for detecting swap activity
  3412. #
  3413. # arguments for vmstat are OS dependant
  3414. # swap_in and swap_out are in different columns depending on OS
  3415. #
  3416. if(not $script) {
  3417. my %vmstat = (
  3418. # linux: $7*$8
  3419. # $ vmstat 1 2
  3420. # procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
  3421. # r b swpd free buff cache si so bi bo in cs us sy id wa
  3422. # 5 0 51208 1701096 198012 18857888 0 0 37 153 28 19 56 11 33 1
  3423. # 3 0 51208 1701288 198012 18857972 0 0 0 0 3638 10412 15 3 82 0
  3424. 'linux' => ['vmstat 1 2 | tail -n1', '$7*$8'],
  3425. # solaris: $6*$7
  3426. # $ vmstat -S 1 2
  3427. # kthr memory page disk faults cpu
  3428. # r b w swap free si so pi po fr de sr s3 s4 -- -- in sy cs us sy id
  3429. # 0 0 0 4628952 3208408 0 0 3 1 1 0 0 -0 2 0 0 263 613 246 1 2 97
  3430. # 0 0 0 4552504 3166360 0 0 0 0 0 0 0 0 0 0 0 246 213 240 1 1 98
  3431. 'solaris' => ['vmstat -S 1 2 | tail -1', '$6*$7'],
  3432. # darwin (macosx): $21*$22
  3433. # $ vm_stat -c 2 1
  3434. # Mach Virtual Memory Statistics: (page size of 4096 bytes)
  3435. # free active specul inactive throttle wired prgable faults copy 0fill reactive purged file-backed anonymous cmprssed cmprssor dcomprs comprs pageins pageout swapins swapouts
  3436. # 346306 829050 74871 606027 0 240231 90367 544858K 62343596 270837K 14178 415070 570102 939846 356 370 116 922 4019813 4 0 0
  3437. # 345740 830383 74875 606031 0 239234 90369 2696 359 553 0 0 570110 941179 356 370 0 0 0 0 0 0
  3438. 'darwin' => ['vm_stat -c 2 1 | tail -n1', '$21*$22'],
  3439. # ultrix: $12*$13
  3440. # $ vmstat -S 1 2
  3441. # procs faults cpu memory page disk
  3442. # r b w in sy cs us sy id avm fre si so pi po fr de sr s0
  3443. # 1 0 0 4 23 2 3 0 97 7743 217k 0 0 0 0 0 0 0 0
  3444. # 1 0 0 6 40 8 0 1 99 7743 217k 0 0 3 0 0 0 0 0
  3445. 'ultrix' => ['vmstat -S 1 2 | tail -1', '$12*$13'],
  3446. # aix: $6*$7
  3447. # $ vmstat 1 2
  3448. # System configuration: lcpu=1 mem=2048MB
  3449. #
  3450. # kthr memory page faults cpu
  3451. # ----- ----------- ------------------------ ------------ -----------
  3452. # r b avm fre re pi po fr sr cy in sy cs us sy id wa
  3453. # 0 0 333933 241803 0 0 0 0 0 0 10 143 90 0 0 99 0
  3454. # 0 0 334125 241569 0 0 0 0 0 0 37 5368 184 0 9 86 5
  3455. 'aix' => ['vmstat 1 2 | tail -n1', '$6*$7'],
  3456. # freebsd: $8*$9
  3457. # $ vmstat -H 1 2
  3458. # procs memory page disks faults cpu
  3459. # r b w avm fre flt re pi po fr sr ad0 ad1 in sy cs us sy id
  3460. # 1 0 0 596716 19560 32 0 0 0 33 8 0 0 11 220 277 0 0 99
  3461. # 0 0 0 596716 19560 2 0 0 0 0 0 0 0 11 144 263 0 1 99
  3462. 'freebsd' => ['vmstat -H 1 2 | tail -n1', '$8*$9'],
  3463. # mirbsd: $8*$9
  3464. # $ vmstat 1 2
  3465. # procs memory page disks traps cpu
  3466. # r b w avm fre flt re pi po fr sr wd0 cd0 int sys cs us sy id
  3467. # 0 0 0 25776 164968 34 0 0 0 0 0 0 0 230 259 38 4 0 96
  3468. # 0 0 0 25776 164968 24 0 0 0 0 0 0 0 237 275 37 0 0 100
  3469. 'mirbsd' => ['vmstat 1 2 | tail -n1', '$8*$9'],
  3470. # netbsd: $7*$8
  3471. # $ vmstat 1 2
  3472. # procs memory page disks faults cpu
  3473. # r b avm fre flt re pi po fr sr w0 w1 in sy cs us sy id
  3474. # 0 0 138452 6012 54 0 0 0 1 2 3 0 4 100 23 0 0 100
  3475. # 0 0 138456 6008 1 0 0 0 0 0 0 0 7 26 19 0 0 100
  3476. 'netbsd' => ['vmstat 1 2 | tail -n1', '$7*$8'],
  3477. # openbsd: $8*$9
  3478. # $ vmstat 1 2
  3479. # procs memory page disks traps cpu
  3480. # r b w avm fre flt re pi po fr sr wd0 wd1 int sys cs us sy id
  3481. # 0 0 0 76596 109944 73 0 0 0 0 0 0 1 5 259 22 0 1 99
  3482. # 0 0 0 76604 109936 24 0 0 0 0 0 0 0 7 114 20 0 1 99
  3483. 'openbsd' => ['vmstat 1 2 | tail -n1', '$8*$9'],
  3484. # hpux: $8*$9
  3485. # $ vmstat 1 2
  3486. # procs memory page faults cpu
  3487. # r b w avm free re at pi po fr de sr in sy cs us sy id
  3488. # 1 0 0 247211 216476 4 1 0 0 0 0 0 102 73005 54 6 11 83
  3489. # 1 0 0 247211 216421 43 9 0 0 0 0 0 144 1675 96 25269512791222387000 25269512791222387000 105
  3490. 'hpux' => ['vmstat 1 2 | tail -n1', '$8*$9'],
  3491. # dec_osf (tru64): $11*$12
  3492. # $ vmstat 1 2
  3493. # Virtual Memory Statistics: (pagesize = 8192)
  3494. # procs memory pages intr cpu
  3495. # r w u act free wire fault cow zero react pin pout in sy cs us sy id
  3496. # 3 181 36 51K 1895 8696 348M 59M 122M 259 79M 0 5 218 302 4 1 94
  3497. # 3 181 36 51K 1893 8696 3 15 21 0 28 0 4 81 321 1 1 98
  3498. 'dec_osf' => ['vmstat 1 2 | tail -n1', '$11*$12'],
  3499. # gnu (hurd): $7*$8
  3500. # $ vmstat -k 1 2
  3501. # (pagesize: 4, size: 512288, swap size: 894972)
  3502. # free actv inact wired zeroed react pgins pgouts pfaults cowpfs hrat caobj cache swfree
  3503. # 371940 30844 89228 20276 298348 0 48192 19016 756105 99808 98% 876 20628 894972
  3504. # 371940 30844 89228 20276 +0 +0 +0 +0 +42 +2 98% 876 20628 894972
  3505. 'gnu' => ['vmstat -k 1 2 | tail -n1', '$7*$8'],
  3506. # -nto (qnx has no swap)
  3507. #-irix
  3508. #-svr5 (scosysv)
  3509. );
  3510. my $perlscript = "";
  3511. for my $os (keys %vmstat) {
  3512. #q[ { vmstat 1 2 2> /dev/null || vmstat -c 1 2; } | ].
  3513. # q[ awk 'NR!=4{next} NF==17||NF==16{print $7*$8} NF==22{print $21*$22} {exit}' ];
  3514. $vmstat{$os}[1] =~ s/\$/\\\\\\\$/g; # $ => \\\$
  3515. $perlscript .= 'if($^O eq "'.$os.'") { print `'.$vmstat{$os}[0].' | awk "{print ' .
  3516. $vmstat{$os}[1] . '}"` }';
  3517. }
  3518. $perlscript = "perl -e " . ::shell_quote_scalar($perlscript);
  3519. $script = $Global::envvar. " " .$perlscript;
  3520. }
  3521. return $script;
  3522. }
  3523. }
  3524. sub too_fast_remote_login {
  3525. my $self = shift;
  3526. if($self->{'last_login_at'} and $self->{'time_to_login'}) {
  3527. # sshd normally allows 10 simultaneous logins
  3528. # A login takes time_to_login
  3529. # So time_to_login/5 should be safe
  3530. # If now <= last_login + time_to_login/5: Then it is too soon.
  3531. my $too_fast = (::now() <= $self->{'last_login_at'}
  3532. + $self->{'time_to_login'}/5);
  3533. ::debug("run", "Too fast? $too_fast ");
  3534. return $too_fast;
  3535. } else {
  3536. # No logins so far (or time_to_login not computed): it is not too fast
  3537. return 0;
  3538. }
  3539. }
  3540. sub last_login_at {
  3541. my $self = shift;
  3542. return $self->{'last_login_at'};
  3543. }
  3544. sub set_last_login_at {
  3545. my $self = shift;
  3546. $self->{'last_login_at'} = shift;
  3547. }
  3548. sub loadavg_too_high {
  3549. my $self = shift;
  3550. my $loadavg = $self->loadavg();
  3551. return (not defined $loadavg or
  3552. $loadavg > $self->max_loadavg());
  3553. }
  3554. sub loadavg {
  3555. # If the currently know loadavg is too old:
  3556. # Recompute a new one in the background
  3557. # The load average is computed as the number of processes waiting for disk
  3558. # or CPU right now. So it is the server load this instant and not averaged over
  3559. # several minutes. This is needed so GNU Parallel will at most start one job
  3560. # that will push the load over the limit.
  3561. #
  3562. # Returns:
  3563. # $last_loadavg = last load average computed (undef if none)
  3564. my $self = shift;
  3565. # Should we update the loadavg file?
  3566. my $update_loadavg_file = 0;
  3567. if(open(my $load_fh, "<", $self->{'loadavg_file'})) {
  3568. local $/ = undef;
  3569. my $load_out = <$load_fh>;
  3570. close $load_fh;
  3571. my $load =()= ($load_out=~/(^[DR]....[^\[])/gm);
  3572. if($load > 0) {
  3573. # load is overestimated by 1
  3574. $self->{'loadavg'} = $load - 1;
  3575. ::debug("load", "New loadavg: ", $self->{'loadavg'});
  3576. } else {
  3577. ::die_bug("loadavg_invalid_content: $load_out");
  3578. }
  3579. ::debug("load", "Last update: ", $self->{'last_loadavg_update'});
  3580. if(time - $self->{'last_loadavg_update'} > 10) {
  3581. # last loadavg was started 10 seconds ago
  3582. ::debug("load", time - $self->{'last_loadavg_update'}, " secs old: ",
  3583. $self->{'loadavg_file'});
  3584. $update_loadavg_file = 1;
  3585. }
  3586. } else {
  3587. ::debug("load", "No loadavg file: ", $self->{'loadavg_file'});
  3588. $self->{'loadavg'} = undef;
  3589. $update_loadavg_file = 1;
  3590. }
  3591. if($update_loadavg_file) {
  3592. ::debug("load", "Updating loadavg file", $self->{'loadavg_file'}, "\n");
  3593. $self->{'last_loadavg_update'} = time;
  3594. -e $ENV{'HOME'}."/.parallel" or mkdir $ENV{'HOME'}."/.parallel";
  3595. -e $ENV{'HOME'}."/.parallel/tmp" or mkdir $ENV{'HOME'}."/.parallel/tmp";
  3596. my $cmd = "";
  3597. if($self->{'string'} ne ":") {
  3598. $cmd = $self->sshcommand() . " " . $self->serverlogin() . " ";
  3599. }
  3600. # TODO Is is called 'ps ax -o state,command' on other platforms?
  3601. $cmd .= "ps ax -o state,command";
  3602. # As the command can take long to run if run remote
  3603. # save it to a tmp file before moving it to the correct file
  3604. my $file = $self->{'loadavg_file'};
  3605. my ($dummy_fh, $tmpfile) = ::tmpfile(SUFFIX => ".loa");
  3606. qx{ ($cmd > $tmpfile && mv $tmpfile $file || rm $tmpfile) & };
  3607. }
  3608. return $self->{'loadavg'};
  3609. }
  3610. sub max_loadavg {
  3611. my $self = shift;
  3612. # If --load is a file it might be changed
  3613. if($Global::max_load_file) {
  3614. my $mtime = (stat($Global::max_load_file))[9];
  3615. if($mtime > $Global::max_load_file_last_mod) {
  3616. $Global::max_load_file_last_mod = $mtime;
  3617. for my $sshlogin (values %Global::host) {
  3618. $sshlogin->set_max_loadavg(undef);
  3619. }
  3620. }
  3621. }
  3622. if(not defined $self->{'max_loadavg'}) {
  3623. $self->{'max_loadavg'} =
  3624. $self->compute_max_loadavg($opt::load);
  3625. }
  3626. ::debug("load", "max_loadavg: ", $self->string(), " ", $self->{'max_loadavg'});
  3627. return $self->{'max_loadavg'};
  3628. }
  3629. sub set_max_loadavg {
  3630. my $self = shift;
  3631. $self->{'max_loadavg'} = shift;
  3632. }
  3633. sub compute_max_loadavg {
  3634. # Parse the max loadaverage that the user asked for using --load
  3635. # Returns:
  3636. # max loadaverage
  3637. my $self = shift;
  3638. my $loadspec = shift;
  3639. my $load;
  3640. if(defined $loadspec) {
  3641. if($loadspec =~ /^\+(\d+)$/) {
  3642. # E.g. --load +2
  3643. my $j = $1;
  3644. $load =
  3645. $self->ncpus() + $j;
  3646. } elsif ($loadspec =~ /^-(\d+)$/) {
  3647. # E.g. --load -2
  3648. my $j = $1;
  3649. $load =
  3650. $self->ncpus() - $j;
  3651. } elsif ($loadspec =~ /^(\d+)\%$/) {
  3652. my $j = $1;
  3653. $load =
  3654. $self->ncpus() * $j / 100;
  3655. } elsif ($loadspec =~ /^(\d+(\.\d+)?)$/) {
  3656. $load = $1;
  3657. } elsif (-f $loadspec) {
  3658. $Global::max_load_file = $loadspec;
  3659. $Global::max_load_file_last_mod = (stat($Global::max_load_file))[9];
  3660. if(open(my $in_fh, "<", $Global::max_load_file)) {
  3661. my $opt_load_file = join("",<$in_fh>);
  3662. close $in_fh;
  3663. $load = $self->compute_max_loadavg($opt_load_file);
  3664. } else {
  3665. print $Global::original_stderr "Cannot open $loadspec\n";
  3666. ::wait_and_exit(255);
  3667. }
  3668. } else {
  3669. print $Global::original_stderr "Parsing of --load failed\n";
  3670. ::die_usage();
  3671. }
  3672. if($load < 0.01) {
  3673. $load = 0.01;
  3674. }
  3675. }
  3676. return $load;
  3677. }
  3678. sub time_to_login {
  3679. my $self = shift;
  3680. return $self->{'time_to_login'};
  3681. }
  3682. sub set_time_to_login {
  3683. my $self = shift;
  3684. $self->{'time_to_login'} = shift;
  3685. }
  3686. sub max_jobs_running {
  3687. my $self = shift;
  3688. if(not defined $self->{'max_jobs_running'}) {
  3689. my $nproc = $self->compute_number_of_processes($opt::jobs);
  3690. $self->set_max_jobs_running($nproc);
  3691. }
  3692. return $self->{'max_jobs_running'};
  3693. }
  3694. sub orig_max_jobs_running {
  3695. my $self = shift;
  3696. return $self->{'orig_max_jobs_running'};
  3697. }
  3698. sub compute_number_of_processes {
  3699. # Number of processes wanted and limited by system resources
  3700. # Returns:
  3701. # Number of processes
  3702. my $self = shift;
  3703. my $opt_P = shift;
  3704. my $wanted_processes = $self->user_requested_processes($opt_P);
  3705. if(not defined $wanted_processes) {
  3706. $wanted_processes = $Global::default_simultaneous_sshlogins;
  3707. }
  3708. ::debug("load", "Wanted procs: $wanted_processes\n");
  3709. my $system_limit =
  3710. $self->processes_available_by_system_limit($wanted_processes);
  3711. ::debug("load", "Limited to procs: $system_limit\n");
  3712. return $system_limit;
  3713. }
  3714. sub processes_available_by_system_limit {
  3715. # If the wanted number of processes is bigger than the system limits:
  3716. # Limit them to the system limits
  3717. # Limits are: File handles, number of input lines, processes,
  3718. # and taking > 1 second to spawn 10 extra processes
  3719. # Returns:
  3720. # Number of processes
  3721. my $self = shift;
  3722. my $wanted_processes = shift;
  3723. my $system_limit = 0;
  3724. my @jobs = ();
  3725. my $job;
  3726. my @args = ();
  3727. my $arg;
  3728. my $more_filehandles = 1;
  3729. my $max_system_proc_reached = 0;
  3730. my $slow_spawining_warning_printed = 0;
  3731. my $time = time;
  3732. my %fh;
  3733. my @children;
  3734. # Reserve filehandles
  3735. # perl uses 7 filehandles for something?
  3736. # parallel uses 1 for memory_usage
  3737. # parallel uses 4 for ?
  3738. for my $i (1..12) {
  3739. open($fh{"init-$i"}, "<", "/dev/null");
  3740. }
  3741. for(1..2) {
  3742. # System process limit
  3743. my $child;
  3744. if($child = fork()) {
  3745. push (@children,$child);
  3746. $Global::unkilled_children{$child} = 1;
  3747. } elsif(defined $child) {
  3748. # The child takes one process slot
  3749. # It will be killed later
  3750. $SIG{TERM} = $Global::original_sig{TERM};
  3751. sleep 10000000;
  3752. exit(0);
  3753. } else {
  3754. $max_system_proc_reached = 1;
  3755. }
  3756. }
  3757. my $count_jobs_already_read = $Global::JobQueue->next_seq();
  3758. my $wait_time_for_getting_args = 0;
  3759. my $start_time = time;
  3760. while(1) {
  3761. $system_limit >= $wanted_processes and last;
  3762. not $more_filehandles and last;
  3763. $max_system_proc_reached and last;
  3764. my $before_getting_arg = time;
  3765. if($Global::semaphore or $opt::pipe) {
  3766. # Skip: No need to get args
  3767. } elsif(defined $opt::retries and $count_jobs_already_read) {
  3768. # For retries we may need to run all jobs on this sshlogin
  3769. # so include the already read jobs for this sshlogin
  3770. $count_jobs_already_read--;
  3771. } else {
  3772. if($opt::X or $opt::m) {
  3773. # The arguments may have to be re-spread over several jobslots
  3774. # So pessimistically only read one arg per jobslot
  3775. # instead of a full commandline
  3776. if($Global::JobQueue->{'commandlinequeue'}->{'arg_queue'}->empty()) {
  3777. if($Global::JobQueue->empty()) {
  3778. last;
  3779. } else {
  3780. ($job) = $Global::JobQueue->get();
  3781. push(@jobs, $job);
  3782. }
  3783. } else {
  3784. ($arg) = $Global::JobQueue->{'commandlinequeue'}->{'arg_queue'}->get();
  3785. push(@args, $arg);
  3786. }
  3787. } else {
  3788. # If there are no more command lines, then we have a process
  3789. # per command line, so no need to go further
  3790. $Global::JobQueue->empty() and last;
  3791. ($job) = $Global::JobQueue->get();
  3792. push(@jobs, $job);
  3793. }
  3794. }
  3795. $wait_time_for_getting_args += time - $before_getting_arg;
  3796. $system_limit++;
  3797. # Every simultaneous process uses 2 filehandles when grouping
  3798. # Every simultaneous process uses 2 filehandles when compressing
  3799. $more_filehandles = open($fh{$system_limit*10}, "<", "/dev/null")
  3800. && open($fh{$system_limit*10+2}, "<", "/dev/null")
  3801. && open($fh{$system_limit*10+3}, "<", "/dev/null")
  3802. && open($fh{$system_limit*10+4}, "<", "/dev/null");
  3803. # System process limit
  3804. my $child;
  3805. if($child = fork()) {
  3806. push (@children,$child);
  3807. $Global::unkilled_children{$child} = 1;
  3808. } elsif(defined $child) {
  3809. # The child takes one process slot
  3810. # It will be killed later
  3811. $SIG{TERM} = $Global::original_sig{TERM};
  3812. sleep 10000000;
  3813. exit(0);
  3814. } else {
  3815. $max_system_proc_reached = 1;
  3816. }
  3817. my $forktime = time - $time - $wait_time_for_getting_args;
  3818. ::debug("run", "Time to fork $system_limit procs: $wait_time_for_getting_args ",
  3819. $forktime,
  3820. " (processes so far: ", $system_limit,")\n");
  3821. if($system_limit > 10 and
  3822. $forktime > 1 and
  3823. $forktime > $system_limit * 0.01
  3824. and not $slow_spawining_warning_printed) {
  3825. # It took more than 0.01 second to fork a processes on avg.
  3826. # Give the user a warning. He can press Ctrl-C if this
  3827. # sucks.
  3828. print $Global::original_stderr
  3829. ("parallel: Warning: Starting $system_limit processes took > $forktime sec.\n",
  3830. "Consider adjusting -j. Press CTRL-C to stop.\n");
  3831. $slow_spawining_warning_printed = 1;
  3832. }
  3833. }
  3834. # Cleanup: Close the files
  3835. for (values %fh) { close $_ }
  3836. # Cleanup: Kill the children
  3837. for my $pid (@children) {
  3838. kill 9, $pid;
  3839. waitpid($pid,0);
  3840. delete $Global::unkilled_children{$pid};
  3841. }
  3842. # Cleanup: Unget the command_lines or the @args
  3843. $Global::JobQueue->{'commandlinequeue'}->{'arg_queue'}->unget(@args);
  3844. $Global::JobQueue->unget(@jobs);
  3845. if($system_limit < $wanted_processes) {
  3846. # The system_limit is less than the wanted_processes
  3847. if($system_limit < 1 and not $Global::JobQueue->empty()) {
  3848. ::warning("Cannot spawn any jobs. Raising ulimit -u or /etc/security/limits.conf\n",
  3849. "or /proc/sys/kernel/pid_max may help.\n");
  3850. ::wait_and_exit(255);
  3851. }
  3852. if(not $more_filehandles) {
  3853. ::warning("Only enough file handles to run ", $system_limit, " jobs in parallel.\n",
  3854. "Running 'parallel -j0 -N", $system_limit, " --pipe parallel -j0' or ",
  3855. "raising ulimit -n or /etc/security/limits.conf may help.\n");
  3856. }
  3857. if($max_system_proc_reached) {
  3858. ::warning("Only enough available processes to run ", $system_limit,
  3859. " jobs in parallel. Raising ulimit -u or /etc/security/limits.conf\n",
  3860. "or /proc/sys/kernel/pid_max may help.\n");
  3861. }
  3862. }
  3863. if($] == 5.008008 and $system_limit > 1000) {
  3864. # https://savannah.gnu.org/bugs/?36942
  3865. $system_limit = 1000;
  3866. }
  3867. if($Global::JobQueue->empty()) {
  3868. $system_limit ||= 1;
  3869. }
  3870. if($self->string() ne ":" and
  3871. $system_limit > $Global::default_simultaneous_sshlogins) {
  3872. $system_limit =
  3873. $self->simultaneous_sshlogin_limit($system_limit);
  3874. }
  3875. return $system_limit;
  3876. }
  3877. sub simultaneous_sshlogin_limit {
  3878. # Test by logging in wanted number of times simultaneously
  3879. # Returns:
  3880. # min($wanted_processes,$working_simultaneous_ssh_logins-1)
  3881. my $self = shift;
  3882. my $wanted_processes = shift;
  3883. if($self->{'time_to_login'}) {
  3884. return $wanted_processes;
  3885. }
  3886. # Try twice because it guesses wrong sometimes
  3887. # Choose the minimal
  3888. my $ssh_limit =
  3889. ::min($self->simultaneous_sshlogin($wanted_processes),
  3890. $self->simultaneous_sshlogin($wanted_processes));
  3891. if($ssh_limit < $wanted_processes) {
  3892. my $serverlogin = $self->serverlogin();
  3893. ::warning("ssh to $serverlogin only allows ",
  3894. "for $ssh_limit simultaneous logins.\n",
  3895. "You may raise this by changing ",
  3896. "/etc/ssh/sshd_config:MaxStartups and MaxSessions on $serverlogin.\n",
  3897. "Using only ",$ssh_limit-1," connections ",
  3898. "to avoid race conditions.\n");
  3899. }
  3900. # Race condition can cause problem if using all sshs.
  3901. if($ssh_limit > 1) { $ssh_limit -= 1; }
  3902. return $ssh_limit;
  3903. }
  3904. sub simultaneous_sshlogin {
  3905. # Using $sshlogin try to see if we can do $wanted_processes
  3906. # simultaneous logins
  3907. # (ssh host echo simultaneouslogin & ssh host echo simultaneouslogin & ...)|grep simul|wc -l
  3908. # Returns:
  3909. # Number of succesful logins
  3910. my $self = shift;
  3911. my $wanted_processes = shift;
  3912. my $sshcmd = $self->sshcommand();
  3913. my $serverlogin = $self->serverlogin();
  3914. my $sshdelay = $opt::sshdelay ? "sleep $opt::sshdelay;" : "";
  3915. my $cmd = "$sshdelay$sshcmd $serverlogin echo simultaneouslogin </dev/null 2>&1 &"x$wanted_processes;
  3916. ::debug("init", "Trying $wanted_processes logins at $serverlogin\n");
  3917. open (my $simul_fh, "-|", "($cmd)|grep simultaneouslogin | wc -l") or
  3918. ::die_bug("simultaneouslogin");
  3919. my $ssh_limit = <$simul_fh>;
  3920. close $simul_fh;
  3921. chomp $ssh_limit;
  3922. return $ssh_limit;
  3923. }
  3924. sub set_ncpus {
  3925. my $self = shift;
  3926. $self->{'ncpus'} = shift;
  3927. }
  3928. sub user_requested_processes {
  3929. # Parse the number of processes that the user asked for using -j
  3930. # Returns:
  3931. # the number of processes to run on this sshlogin
  3932. my $self = shift;
  3933. my $opt_P = shift;
  3934. my $processes;
  3935. if(defined $opt_P) {
  3936. if($opt_P =~ /^\+(\d+)$/) {
  3937. # E.g. -P +2
  3938. my $j = $1;
  3939. $processes =
  3940. $self->ncpus() + $j;
  3941. } elsif ($opt_P =~ /^-(\d+)$/) {
  3942. # E.g. -P -2
  3943. my $j = $1;
  3944. $processes =
  3945. $self->ncpus() - $j;
  3946. } elsif ($opt_P =~ /^(\d+(\.\d+)?)\%$/) {
  3947. # E.g. -P 10.5%
  3948. my $j = $1;
  3949. $processes =
  3950. $self->ncpus() * $j / 100;
  3951. } elsif ($opt_P =~ /^(\d+)$/) {
  3952. $processes = $1;
  3953. if($processes == 0) {
  3954. # -P 0 = infinity (or at least close)
  3955. $processes = $Global::infinity;
  3956. }
  3957. } elsif (-f $opt_P) {
  3958. $Global::max_procs_file = $opt_P;
  3959. $Global::max_procs_file_last_mod = (stat($Global::max_procs_file))[9];
  3960. if(open(my $in_fh, "<", $Global::max_procs_file)) {
  3961. my $opt_P_file = join("",<$in_fh>);
  3962. close $in_fh;
  3963. $processes = $self->user_requested_processes($opt_P_file);
  3964. } else {
  3965. ::error("Cannot open $opt_P.\n");
  3966. ::wait_and_exit(255);
  3967. }
  3968. } else {
  3969. ::error("Parsing of --jobs/-j/--max-procs/-P failed.\n");
  3970. ::die_usage();
  3971. }
  3972. $processes = ::ceil($processes);
  3973. }
  3974. return $processes;
  3975. }
  3976. sub ncpus {
  3977. my $self = shift;
  3978. if(not defined $self->{'ncpus'}) {
  3979. my $sshcmd = $self->sshcommand();
  3980. my $serverlogin = $self->serverlogin();
  3981. if($serverlogin eq ":") {
  3982. if($opt::use_cpus_instead_of_cores) {
  3983. $self->{'ncpus'} = no_of_cpus();
  3984. } else {
  3985. $self->{'ncpus'} = no_of_cores();
  3986. }
  3987. } else {
  3988. my $ncpu;
  3989. my $sqe = ::shell_quote_scalar($Global::envvar);
  3990. if($opt::use_cpus_instead_of_cores) {
  3991. $ncpu = qx(echo|$sshcmd $serverlogin $sqe parallel --number-of-cpus);
  3992. } else {
  3993. ::debug("init",qq(echo|$sshcmd $serverlogin $sqe parallel --number-of-cores\n));
  3994. $ncpu = qx(echo|$sshcmd $serverlogin $sqe parallel --number-of-cores);
  3995. }
  3996. chomp $ncpu;
  3997. if($ncpu =~ /^\s*[0-9]+\s*$/s) {
  3998. $self->{'ncpus'} = $ncpu;
  3999. } else {
  4000. ::warning("Could not figure out ",
  4001. "number of cpus on $serverlogin ($ncpu). Using 1.\n");
  4002. $self->{'ncpus'} = 1;
  4003. }
  4004. }
  4005. }
  4006. return $self->{'ncpus'};
  4007. }
  4008. sub no_of_cpus {
  4009. # Returns:
  4010. # Number of physical CPUs
  4011. local $/="\n"; # If delimiter is set, then $/ will be wrong
  4012. my $no_of_cpus;
  4013. if ($^O eq 'linux') {
  4014. $no_of_cpus = no_of_cpus_gnu_linux() || no_of_cores_gnu_linux();
  4015. } elsif ($^O eq 'freebsd') {
  4016. $no_of_cpus = no_of_cpus_freebsd();
  4017. } elsif ($^O eq 'netbsd') {
  4018. $no_of_cpus = no_of_cpus_netbsd();
  4019. } elsif ($^O eq 'openbsd') {
  4020. $no_of_cpus = no_of_cpus_openbsd();
  4021. } elsif ($^O eq 'gnu') {
  4022. $no_of_cpus = no_of_cpus_hurd();
  4023. } elsif ($^O eq 'darwin') {
  4024. $no_of_cpus = no_of_cpus_darwin();
  4025. } elsif ($^O eq 'solaris') {
  4026. $no_of_cpus = no_of_cpus_solaris();
  4027. } elsif ($^O eq 'aix') {
  4028. $no_of_cpus = no_of_cpus_aix();
  4029. } elsif ($^O eq 'hpux') {
  4030. $no_of_cpus = no_of_cpus_hpux();
  4031. } elsif ($^O eq 'nto') {
  4032. $no_of_cpus = no_of_cpus_qnx();
  4033. } elsif ($^O eq 'svr5') {
  4034. $no_of_cpus = no_of_cpus_openserver();
  4035. } elsif ($^O eq 'irix') {
  4036. $no_of_cpus = no_of_cpus_irix();
  4037. } elsif ($^O eq 'dec_osf') {
  4038. $no_of_cpus = no_of_cpus_tru64();
  4039. } else {
  4040. $no_of_cpus = (no_of_cpus_gnu_linux()
  4041. || no_of_cpus_freebsd()
  4042. || no_of_cpus_netbsd()
  4043. || no_of_cpus_openbsd()
  4044. || no_of_cpus_hurd()
  4045. || no_of_cpus_darwin()
  4046. || no_of_cpus_solaris()
  4047. || no_of_cpus_aix()
  4048. || no_of_cpus_hpux()
  4049. || no_of_cpus_qnx()
  4050. || no_of_cpus_openserver()
  4051. || no_of_cpus_irix()
  4052. || no_of_cpus_tru64()
  4053. # Number of cores is better than no guess for #CPUs
  4054. || nproc()
  4055. );
  4056. }
  4057. if($no_of_cpus) {
  4058. chomp $no_of_cpus;
  4059. return $no_of_cpus;
  4060. } else {
  4061. ::warning("Cannot figure out number of cpus. Using 1.\n");
  4062. return 1;
  4063. }
  4064. }
  4065. sub no_of_cores {
  4066. # Returns:
  4067. # Number of CPU cores
  4068. local $/="\n"; # If delimiter is set, then $/ will be wrong
  4069. my $no_of_cores;
  4070. if ($^O eq 'linux') {
  4071. $no_of_cores = no_of_cores_gnu_linux();
  4072. } elsif ($^O eq 'freebsd') {
  4073. $no_of_cores = no_of_cores_freebsd();
  4074. } elsif ($^O eq 'netbsd') {
  4075. $no_of_cores = no_of_cores_netbsd();
  4076. } elsif ($^O eq 'openbsd') {
  4077. $no_of_cores = no_of_cores_openbsd();
  4078. } elsif ($^O eq 'gnu') {
  4079. $no_of_cores = no_of_cores_hurd();
  4080. } elsif ($^O eq 'darwin') {
  4081. $no_of_cores = no_of_cores_darwin();
  4082. } elsif ($^O eq 'solaris') {
  4083. $no_of_cores = no_of_cores_solaris();
  4084. } elsif ($^O eq 'aix') {
  4085. $no_of_cores = no_of_cores_aix();
  4086. } elsif ($^O eq 'hpux') {
  4087. $no_of_cores = no_of_cores_hpux();
  4088. } elsif ($^O eq 'nto') {
  4089. $no_of_cores = no_of_cores_qnx();
  4090. } elsif ($^O eq 'svr5') {
  4091. $no_of_cores = no_of_cores_openserver();
  4092. } elsif ($^O eq 'irix') {
  4093. $no_of_cores = no_of_cores_irix();
  4094. } elsif ($^O eq 'dec_osf') {
  4095. $no_of_cores = no_of_cores_tru64();
  4096. } else {
  4097. $no_of_cores = (no_of_cores_gnu_linux()
  4098. || no_of_cores_freebsd()
  4099. || no_of_cores_netbsd()
  4100. || no_of_cores_openbsd()
  4101. || no_of_cores_hurd()
  4102. || no_of_cores_darwin()
  4103. || no_of_cores_solaris()
  4104. || no_of_cores_aix()
  4105. || no_of_cores_hpux()
  4106. || no_of_cores_qnx()
  4107. || no_of_cores_openserver()
  4108. || no_of_cores_irix()
  4109. || no_of_cores_tru64()
  4110. || nproc()
  4111. );
  4112. }
  4113. if($no_of_cores) {
  4114. chomp $no_of_cores;
  4115. return $no_of_cores;
  4116. } else {
  4117. ::warning("Cannot figure out number of CPU cores. Using 1.\n");
  4118. return 1;
  4119. }
  4120. }
  4121. sub nproc {
  4122. # Returns:
  4123. # Number of cores using `nproc`
  4124. my $no_of_cores = `nproc 2>/dev/null`;
  4125. return $no_of_cores;
  4126. }
  4127. sub no_of_cpus_gnu_linux {
  4128. # Returns:
  4129. # Number of physical CPUs on GNU/Linux
  4130. # undef if not GNU/Linux
  4131. my $no_of_cpus;
  4132. my $no_of_cores;
  4133. if(-e "/proc/cpuinfo") {
  4134. $no_of_cpus = 0;
  4135. $no_of_cores = 0;
  4136. my %seen;
  4137. open(my $in_fh, "<", "/proc/cpuinfo") || return undef;
  4138. while(<$in_fh>) {
  4139. if(/^physical id.*[:](.*)/ and not $seen{$1}++) {
  4140. $no_of_cpus++;
  4141. }
  4142. /^processor.*[:]/i and $no_of_cores++;
  4143. }
  4144. close $in_fh;
  4145. }
  4146. return ($no_of_cpus||$no_of_cores);
  4147. }
  4148. sub no_of_cores_gnu_linux {
  4149. # Returns:
  4150. # Number of CPU cores on GNU/Linux
  4151. # undef if not GNU/Linux
  4152. my $no_of_cores;
  4153. if(-e "/proc/cpuinfo") {
  4154. $no_of_cores = 0;
  4155. open(my $in_fh, "<", "/proc/cpuinfo") || return undef;
  4156. while(<$in_fh>) {
  4157. /^processor.*[:]/i and $no_of_cores++;
  4158. }
  4159. close $in_fh;
  4160. }
  4161. return $no_of_cores;
  4162. }
  4163. sub no_of_cpus_freebsd {
  4164. # Returns:
  4165. # Number of physical CPUs on FreeBSD
  4166. # undef if not FreeBSD
  4167. my $no_of_cpus =
  4168. (`sysctl -a dev.cpu 2>/dev/null | grep \%parent | awk '{ print \$2 }' | uniq | wc -l | awk '{ print \$1 }'`
  4169. or
  4170. `sysctl hw.ncpu 2>/dev/null | awk '{ print \$2 }'`);
  4171. chomp $no_of_cpus;
  4172. return $no_of_cpus;
  4173. }
  4174. sub no_of_cores_freebsd {
  4175. # Returns:
  4176. # Number of CPU cores on FreeBSD
  4177. # undef if not FreeBSD
  4178. my $no_of_cores =
  4179. (`sysctl hw.ncpu 2>/dev/null | awk '{ print \$2 }'`
  4180. or
  4181. `sysctl -a hw 2>/dev/null | grep [^a-z]logicalcpu[^a-z] | awk '{ print \$2 }'`);
  4182. chomp $no_of_cores;
  4183. return $no_of_cores;
  4184. }
  4185. sub no_of_cpus_netbsd {
  4186. # Returns:
  4187. # Number of physical CPUs on NetBSD
  4188. # undef if not NetBSD
  4189. my $no_of_cpus = `sysctl -n hw.ncpu 2>/dev/null`;
  4190. chomp $no_of_cpus;
  4191. return $no_of_cpus;
  4192. }
  4193. sub no_of_cores_netbsd {
  4194. # Returns:
  4195. # Number of CPU cores on NetBSD
  4196. # undef if not NetBSD
  4197. my $no_of_cores = `sysctl -n hw.ncpu 2>/dev/null`;
  4198. chomp $no_of_cores;
  4199. return $no_of_cores;
  4200. }
  4201. sub no_of_cpus_openbsd {
  4202. # Returns:
  4203. # Number of physical CPUs on OpenBSD
  4204. # undef if not OpenBSD
  4205. my $no_of_cpus = `sysctl -n hw.ncpu 2>/dev/null`;
  4206. chomp $no_of_cpus;
  4207. return $no_of_cpus;
  4208. }
  4209. sub no_of_cores_openbsd {
  4210. # Returns:
  4211. # Number of CPU cores on OpenBSD
  4212. # undef if not OpenBSD
  4213. my $no_of_cores = `sysctl -n hw.ncpu 2>/dev/null`;
  4214. chomp $no_of_cores;
  4215. return $no_of_cores;
  4216. }
  4217. sub no_of_cpus_hurd {
  4218. # Returns:
  4219. # Number of physical CPUs on HURD
  4220. # undef if not HURD
  4221. my $no_of_cpus = `nproc`;
  4222. chomp $no_of_cpus;
  4223. return $no_of_cpus;
  4224. }
  4225. sub no_of_cores_hurd {
  4226. # Returns:
  4227. # Number of physical CPUs on HURD
  4228. # undef if not HURD
  4229. my $no_of_cores = `nproc`;
  4230. chomp $no_of_cores;
  4231. return $no_of_cores;
  4232. }
  4233. sub no_of_cpus_darwin {
  4234. # Returns:
  4235. # Number of physical CPUs on Mac Darwin
  4236. # undef if not Mac Darwin
  4237. my $no_of_cpus =
  4238. (`sysctl -n hw.physicalcpu 2>/dev/null`
  4239. or
  4240. `sysctl -a hw 2>/dev/null | grep [^a-z]physicalcpu[^a-z] | awk '{ print \$2 }'`);
  4241. return $no_of_cpus;
  4242. }
  4243. sub no_of_cores_darwin {
  4244. # Returns:
  4245. # Number of CPU cores on Mac Darwin
  4246. # undef if not Mac Darwin
  4247. my $no_of_cores =
  4248. (`sysctl -n hw.logicalcpu 2>/dev/null`
  4249. or
  4250. `sysctl -a hw 2>/dev/null | grep [^a-z]logicalcpu[^a-z] | awk '{ print \$2 }'`);
  4251. return $no_of_cores;
  4252. }
  4253. sub no_of_cpus_solaris {
  4254. # Returns:
  4255. # Number of physical CPUs on Solaris
  4256. # undef if not Solaris
  4257. if(-x "/usr/sbin/psrinfo") {
  4258. my @psrinfo = `/usr/sbin/psrinfo`;
  4259. if($#psrinfo >= 0) {
  4260. return $#psrinfo +1;
  4261. }
  4262. }
  4263. if(-x "/usr/sbin/prtconf") {
  4264. my @prtconf = `/usr/sbin/prtconf | grep cpu..instance`;
  4265. if($#prtconf >= 0) {
  4266. return $#prtconf +1;
  4267. }
  4268. }
  4269. return undef;
  4270. }
  4271. sub no_of_cores_solaris {
  4272. # Returns:
  4273. # Number of CPU cores on Solaris
  4274. # undef if not Solaris
  4275. if(-x "/usr/sbin/psrinfo") {
  4276. my @psrinfo = `/usr/sbin/psrinfo`;
  4277. if($#psrinfo >= 0) {
  4278. return $#psrinfo +1;
  4279. }
  4280. }
  4281. if(-x "/usr/sbin/prtconf") {
  4282. my @prtconf = `/usr/sbin/prtconf | grep cpu..instance`;
  4283. if($#prtconf >= 0) {
  4284. return $#prtconf +1;
  4285. }
  4286. }
  4287. return undef;
  4288. }
  4289. sub no_of_cpus_aix {
  4290. # Returns:
  4291. # Number of physical CPUs on AIX
  4292. # undef if not AIX
  4293. my $no_of_cpus = 0;
  4294. if(-x "/usr/sbin/lscfg") {
  4295. open(my $in_fh, "-|", "/usr/sbin/lscfg -vs |grep proc | wc -l|tr -d ' '")
  4296. || return undef;
  4297. $no_of_cpus = <$in_fh>;
  4298. chomp ($no_of_cpus);
  4299. close $in_fh;
  4300. }
  4301. return $no_of_cpus;
  4302. }
  4303. sub no_of_cores_aix {
  4304. # Returns:
  4305. # Number of CPU cores on AIX
  4306. # undef if not AIX
  4307. my $no_of_cores;
  4308. if(-x "/usr/bin/vmstat") {
  4309. open(my $in_fh, "-|", "/usr/bin/vmstat 1 1") || return undef;
  4310. while(<$in_fh>) {
  4311. /lcpu=([0-9]*) / and $no_of_cores = $1;
  4312. }
  4313. close $in_fh;
  4314. }
  4315. return $no_of_cores;
  4316. }
  4317. sub no_of_cpus_hpux {
  4318. # Returns:
  4319. # Number of physical CPUs on HP-UX
  4320. # undef if not HP-UX
  4321. my $no_of_cpus =
  4322. (`/usr/bin/mpsched -s 2>&1 | grep 'Locality Domain Count' | awk '{ print \$4 }'`);
  4323. return $no_of_cpus;
  4324. }
  4325. sub no_of_cores_hpux {
  4326. # Returns:
  4327. # Number of CPU cores on HP-UX
  4328. # undef if not HP-UX
  4329. my $no_of_cores =
  4330. (`/usr/bin/mpsched -s 2>&1 | grep 'Processor Count' | awk '{ print \$3 }'`);
  4331. return $no_of_cores;
  4332. }
  4333. sub no_of_cpus_qnx {
  4334. # Returns:
  4335. # Number of physical CPUs on QNX
  4336. # undef if not QNX
  4337. # BUG: It is now known how to calculate this.
  4338. my $no_of_cpus = 0;
  4339. return $no_of_cpus;
  4340. }
  4341. sub no_of_cores_qnx {
  4342. # Returns:
  4343. # Number of CPU cores on QNX
  4344. # undef if not QNX
  4345. # BUG: It is now known how to calculate this.
  4346. my $no_of_cores = 0;
  4347. return $no_of_cores;
  4348. }
  4349. sub no_of_cpus_openserver {
  4350. # Returns:
  4351. # Number of physical CPUs on SCO OpenServer
  4352. # undef if not SCO OpenServer
  4353. my $no_of_cpus = 0;
  4354. if(-x "/usr/sbin/psrinfo") {
  4355. my @psrinfo = `/usr/sbin/psrinfo`;
  4356. if($#psrinfo >= 0) {
  4357. return $#psrinfo +1;
  4358. }
  4359. }
  4360. return $no_of_cpus;
  4361. }
  4362. sub no_of_cores_openserver {
  4363. # Returns:
  4364. # Number of CPU cores on SCO OpenServer
  4365. # undef if not SCO OpenServer
  4366. my $no_of_cores = 0;
  4367. if(-x "/usr/sbin/psrinfo") {
  4368. my @psrinfo = `/usr/sbin/psrinfo`;
  4369. if($#psrinfo >= 0) {
  4370. return $#psrinfo +1;
  4371. }
  4372. }
  4373. return $no_of_cores;
  4374. }
  4375. sub no_of_cpus_irix {
  4376. # Returns:
  4377. # Number of physical CPUs on IRIX
  4378. # undef if not IRIX
  4379. my $no_of_cpus = `hinv | grep HZ | grep Processor | awk '{print \$1}'`;
  4380. return $no_of_cpus;
  4381. }
  4382. sub no_of_cores_irix {
  4383. # Returns:
  4384. # Number of CPU cores on IRIX
  4385. # undef if not IRIX
  4386. my $no_of_cores = `hinv | grep HZ | grep Processor | awk '{print \$1}'`;
  4387. return $no_of_cores;
  4388. }
  4389. sub no_of_cpus_tru64 {
  4390. # Returns:
  4391. # Number of physical CPUs on Tru64
  4392. # undef if not Tru64
  4393. my $no_of_cpus = `sizer -pr`;
  4394. return $no_of_cpus;
  4395. }
  4396. sub no_of_cores_tru64 {
  4397. # Returns:
  4398. # Number of CPU cores on Tru64
  4399. # undef if not Tru64
  4400. my $no_of_cores = `sizer -pr`;
  4401. return $no_of_cores;
  4402. }
  4403. sub sshcommand {
  4404. my $self = shift;
  4405. if (not defined $self->{'sshcommand'}) {
  4406. $self->sshcommand_of_sshlogin();
  4407. }
  4408. return $self->{'sshcommand'};
  4409. }
  4410. sub serverlogin {
  4411. my $self = shift;
  4412. if (not defined $self->{'serverlogin'}) {
  4413. $self->sshcommand_of_sshlogin();
  4414. }
  4415. return $self->{'serverlogin'};
  4416. }
  4417. sub sshcommand_of_sshlogin {
  4418. # 'server' -> ('ssh -S /tmp/parallel-ssh-RANDOM/host-','server')
  4419. # 'user@server' -> ('ssh','user@server')
  4420. # 'myssh user@server' -> ('myssh','user@server')
  4421. # 'myssh -l user server' -> ('myssh -l user','server')
  4422. # '/usr/bin/myssh -l user server' -> ('/usr/bin/myssh -l user','server')
  4423. # Returns:
  4424. # sshcommand - defaults to 'ssh'
  4425. # login@host
  4426. my $self = shift;
  4427. my ($sshcmd, $serverlogin);
  4428. if($self->{'string'} =~ /(.+) (\S+)$/) {
  4429. # Own ssh command
  4430. $sshcmd = $1; $serverlogin = $2;
  4431. } else {
  4432. # Normal ssh
  4433. if($opt::controlmaster) {
  4434. # Use control_path to make ssh faster
  4435. my $control_path = $self->control_path_dir()."/ssh-%r@%h:%p";
  4436. $sshcmd = "ssh -S ".$control_path;
  4437. $serverlogin = $self->{'string'};
  4438. if(not $self->{'control_path'}{$control_path}++) {
  4439. # Master is not running for this control_path
  4440. # Start it
  4441. my $pid = fork();
  4442. if($pid) {
  4443. $Global::sshmaster{$pid} ||= 1;
  4444. } else {
  4445. $SIG{'TERM'} = undef;
  4446. # Ignore the 'foo' being printed
  4447. open(STDOUT,">","/dev/null");
  4448. # OpenSSH_3.6.1p2 gives 'tcgetattr: Invalid argument' with -tt
  4449. # STDERR >/dev/null to ignore "process_mux_new_session: tcgetattr: Invalid argument"
  4450. open(STDERR,">","/dev/null");
  4451. open(STDIN,"<","/dev/null");
  4452. # Run a sleep that outputs data, so it will discover if the ssh connection closes.
  4453. my $sleep = ::shell_quote_scalar('$|=1;while(1){sleep 1;print "foo\n"}');
  4454. my @master = ("ssh", "-tt", "-MTS", $control_path, $serverlogin, "perl", "-e", $sleep);
  4455. exec(@master);
  4456. }
  4457. }
  4458. } else {
  4459. $sshcmd = "ssh"; $serverlogin = $self->{'string'};
  4460. }
  4461. }
  4462. $self->{'sshcommand'} = $sshcmd;
  4463. $self->{'serverlogin'} = $serverlogin;
  4464. }
  4465. sub control_path_dir {
  4466. # Returns:
  4467. # path to directory
  4468. my $self = shift;
  4469. if(not defined $self->{'control_path_dir'}) {
  4470. -e $ENV{'HOME'}."/.parallel" or mkdir $ENV{'HOME'}."/.parallel";
  4471. -e $ENV{'HOME'}."/.parallel/tmp" or mkdir $ENV{'HOME'}."/.parallel/tmp";
  4472. $self->{'control_path_dir'} =
  4473. File::Temp::tempdir($ENV{'HOME'}
  4474. . "/.parallel/tmp/control_path_dir-XXXX",
  4475. CLEANUP => 1);
  4476. }
  4477. return $self->{'control_path_dir'};
  4478. }
  4479. sub rsync_transfer_cmd {
  4480. # Command to run to transfer a file
  4481. # Input:
  4482. # $file = filename of file to transfer
  4483. # $workdir = destination dir
  4484. # Returns:
  4485. # $cmd = rsync command to run to transfer $file ("" if unreadable)
  4486. my $self = shift;
  4487. my $file = shift;
  4488. my $workdir = shift;
  4489. if(not -r $file) {
  4490. ::warning($file, " is not readable and will not be transferred.\n");
  4491. return "true";
  4492. }
  4493. my $rsync_destdir;
  4494. if($file =~ m:^/:) {
  4495. # rsync /foo/bar /
  4496. $rsync_destdir = "/";
  4497. } else {
  4498. $rsync_destdir = ::shell_quote_file($workdir);
  4499. }
  4500. $file = ::shell_quote_file($file);
  4501. my $sshcmd = $self->sshcommand();
  4502. my $rsync_opt = "-rlDzR -e" . ::shell_quote_scalar($sshcmd);
  4503. my $serverlogin = $self->serverlogin();
  4504. # Make dir if it does not exist
  4505. return "( $sshcmd $serverlogin mkdir -p $rsync_destdir;" .
  4506. rsync()." $rsync_opt $file $serverlogin:$rsync_destdir )";
  4507. }
  4508. sub cleanup_cmd {
  4509. # Command to run to remove the remote file
  4510. # Input:
  4511. # $file = filename to remove
  4512. # $workdir = destination dir
  4513. # Returns:
  4514. # $cmd = ssh command to run to remove $file and empty parent dirs
  4515. my $self = shift;
  4516. my $file = shift;
  4517. my $workdir = shift;
  4518. my $f = $file;
  4519. if($f =~ m:/\./:) {
  4520. # foo/bar/./baz/quux => workdir/baz/quux
  4521. # /foo/bar/./baz/quux => workdir/baz/quux
  4522. $f =~ s:.*/\./:$workdir/:;
  4523. } elsif($f =~ m:^[^/]:) {
  4524. # foo/bar => workdir/foo/bar
  4525. $f = $workdir."/".$f;
  4526. }
  4527. my @subdirs = split m:/:, ::dirname($f);
  4528. my @rmdir;
  4529. my $dir = "";
  4530. for(@subdirs) {
  4531. $dir .= $_."/";
  4532. unshift @rmdir, ::shell_quote_file($dir);
  4533. }
  4534. my $rmdir = @rmdir ? "rmdir @rmdir 2>/dev/null;" : "";
  4535. if(defined $opt::workdir and $opt::workdir eq "...") {
  4536. $rmdir .= "rm -rf " . ::shell_quote_file($workdir).';';
  4537. }
  4538. $f = ::shell_quote_file($f);
  4539. my $sshcmd = $self->sshcommand();
  4540. my $serverlogin = $self->serverlogin();
  4541. return "$sshcmd $serverlogin ".::shell_quote_scalar("(rm -f $f; $rmdir)");
  4542. }
  4543. {
  4544. my $rsync;
  4545. sub rsync {
  4546. # rsync 3.1.x uses protocol 31 which is unsupported by 2.5.7.
  4547. # If the version >= 3.1.0: downgrade to protocol 30
  4548. if(not $rsync) {
  4549. my @out = `rsync --version`;
  4550. for (@out) {
  4551. if(/version (\d+.\d+)(.\d+)?/) {
  4552. if($1 >= 3.1) {
  4553. # Version 3.1.0 or later: Downgrade to protocol 30
  4554. $rsync = "rsync --protocol 30";
  4555. } else {
  4556. $rsync = "rsync";
  4557. }
  4558. }
  4559. }
  4560. $rsync or ::die_bug("Cannot figure out version of rsync: @out");
  4561. }
  4562. return $rsync;
  4563. }
  4564. }
  4565. package JobQueue;
  4566. sub new {
  4567. my $class = shift;
  4568. my $commandref = shift;
  4569. my $read_from = shift;
  4570. my $context_replace = shift;
  4571. my $max_number_of_args = shift;
  4572. my $return_files = shift;
  4573. my $commandlinequeue = CommandLineQueue->new
  4574. ($commandref, $read_from, $context_replace, $max_number_of_args,
  4575. $return_files);
  4576. my @unget = ();
  4577. return bless {
  4578. 'unget' => \@unget,
  4579. 'commandlinequeue' => $commandlinequeue,
  4580. 'total_jobs' => undef,
  4581. }, ref($class) || $class;
  4582. }
  4583. sub get {
  4584. my $self = shift;
  4585. if(@{$self->{'unget'}}) {
  4586. my $job = shift @{$self->{'unget'}};
  4587. return ($job);
  4588. } else {
  4589. my $commandline = $self->{'commandlinequeue'}->get();
  4590. if(defined $commandline) {
  4591. my $job = Job->new($commandline);
  4592. return $job;
  4593. } else {
  4594. return undef;
  4595. }
  4596. }
  4597. }
  4598. sub unget {
  4599. my $self = shift;
  4600. unshift @{$self->{'unget'}}, @_;
  4601. }
  4602. sub empty {
  4603. my $self = shift;
  4604. my $empty = (not @{$self->{'unget'}})
  4605. && $self->{'commandlinequeue'}->empty();
  4606. ::debug("run", "JobQueue->empty $empty ");
  4607. return $empty;
  4608. }
  4609. sub total_jobs {
  4610. my $self = shift;
  4611. if(not defined $self->{'total_jobs'}) {
  4612. my $job;
  4613. my @queue;
  4614. my $start = time;
  4615. while($job = $self->get()) {
  4616. if(time - $start > 10) {
  4617. ::warning("Reading all arguments takes longer than 10 seconds.\n");
  4618. $opt::eta && ::warning("Consider removing --eta.\n");
  4619. $opt::bar && ::warning("Consider removing --bar.\n");
  4620. last;
  4621. }
  4622. push @queue, $job;
  4623. }
  4624. while($job = $self->get()) {
  4625. push @queue, $job;
  4626. }
  4627. $self->unget(@queue);
  4628. $self->{'total_jobs'} = $#queue+1;
  4629. }
  4630. return $self->{'total_jobs'};
  4631. }
  4632. sub next_seq {
  4633. my $self = shift;
  4634. return $self->{'commandlinequeue'}->seq();
  4635. }
  4636. sub quote_args {
  4637. my $self = shift;
  4638. return $self->{'commandlinequeue'}->quote_args();
  4639. }
  4640. package Job;
  4641. sub new {
  4642. my $class = shift;
  4643. my $commandlineref = shift;
  4644. return bless {
  4645. 'commandline' => $commandlineref, # CommandLine object
  4646. 'workdir' => undef, # --workdir
  4647. 'stdin' => undef, # filehandle for stdin (used for --pipe)
  4648. # filename for writing stdout to (used for --files)
  4649. 'remaining' => "", # remaining data not sent to stdin (used for --pipe)
  4650. 'datawritten' => 0, # amount of data sent via stdin (used for --pipe)
  4651. 'transfersize' => 0, # size of files using --transfer
  4652. 'returnsize' => 0, # size of files using --return
  4653. 'pid' => undef,
  4654. # hash of { SSHLogins => number of times the command failed there }
  4655. 'failed' => undef,
  4656. 'sshlogin' => undef,
  4657. # The commandline wrapped with rsync and ssh
  4658. 'sshlogin_wrap' => undef,
  4659. 'exitstatus' => undef,
  4660. 'exitsignal' => undef,
  4661. # Timestamp for timeout if any
  4662. 'timeout' => undef,
  4663. 'virgin' => 1,
  4664. }, ref($class) || $class;
  4665. }
  4666. sub replaced {
  4667. my $self = shift;
  4668. $self->{'commandline'} or ::die_bug("commandline empty");
  4669. return $self->{'commandline'}->replaced();
  4670. }
  4671. sub seq {
  4672. my $self = shift;
  4673. return $self->{'commandline'}->seq();
  4674. }
  4675. sub slot {
  4676. my $self = shift;
  4677. return $self->{'commandline'}->slot();
  4678. }
  4679. {
  4680. my($cattail);
  4681. sub cattail {
  4682. # Returns:
  4683. # $cattail = perl program for: cattail "decompress program" writerpid [file_to_decompress or stdin] [file_to_unlink]
  4684. if(not $cattail) {
  4685. $cattail = q{
  4686. # cat followed by tail.
  4687. # If $writerpid dead: finish after this round
  4688. use Fcntl;
  4689. $|=1;
  4690. my ($cmd, $writerpid, $read_file, $unlink_file) = @ARGV;
  4691. if($read_file) {
  4692. open(IN,"<",$read_file) || die("cattail: Cannot open $read_file");
  4693. } else {
  4694. *IN = *STDIN;
  4695. }
  4696. my $flags;
  4697. fcntl(IN, F_GETFL, $flags) || die $!; # Get the current flags on the filehandle
  4698. $flags |= O_NONBLOCK; # Add non-blocking to the flags
  4699. fcntl(IN, F_SETFL, $flags) || die $!; # Set the flags on the filehandle
  4700. open(OUT,"|-",$cmd) || die("cattail: Cannot run $cmd");
  4701. while(1) {
  4702. # clear EOF
  4703. seek(IN,0,1);
  4704. my $writer_running = kill 0, $writerpid;
  4705. $read = sysread(IN,$buf,32768);
  4706. if($read) {
  4707. # We can unlink the file now: The writer has written something
  4708. -e $unlink_file and unlink $unlink_file;
  4709. # Blocking print
  4710. while($buf) {
  4711. my $bytes_written = syswrite(OUT,$buf);
  4712. # syswrite may be interrupted by SIGHUP
  4713. substr($buf,0,$bytes_written) = "";
  4714. }
  4715. # Something printed: Wait less next time
  4716. $sleep /= 2;
  4717. } else {
  4718. if(eof(IN) and not $writer_running) {
  4719. # Writer dead: There will never be more to read => exit
  4720. exit;
  4721. }
  4722. # TODO This could probably be done more efficiently using select(2)
  4723. # Nothing read: Wait longer before next read
  4724. # Up to 30 milliseconds
  4725. $sleep = ($sleep < 30) ? ($sleep * 1.001 + 0.01) : ($sleep);
  4726. usleep($sleep);
  4727. }
  4728. }
  4729. sub usleep {
  4730. # Sleep this many milliseconds.
  4731. my $secs = shift;
  4732. select(undef, undef, undef, $secs/1000);
  4733. }
  4734. };
  4735. $cattail =~ s/#.*//mg;
  4736. $cattail =~ s/\s+/ /g;
  4737. }
  4738. return $cattail;
  4739. }
  4740. }
  4741. sub openoutputfiles {
  4742. # Open files for STDOUT and STDERR
  4743. # Set file handles in $self->fh
  4744. my $self = shift;
  4745. my ($outfhw, $errfhw, $outname, $errname);
  4746. if($opt::results) {
  4747. my $args_as_dirname = $self->{'commandline'}->args_as_dirname();
  4748. # Output in: prefix/name1/val1/name2/val2/stdout
  4749. my $dir = $opt::results."/".$args_as_dirname;
  4750. if(eval{ File::Path::mkpath($dir); }) {
  4751. # OK
  4752. } else {
  4753. # mkpath failed: Argument probably too long.
  4754. # Set $Global::max_file_length, which will keep the individual
  4755. # dir names shorter than the max length
  4756. max_file_name_length($opt::results);
  4757. $args_as_dirname = $self->{'commandline'}->args_as_dirname();
  4758. # prefix/name1/val1/name2/val2/
  4759. $dir = $opt::results."/".$args_as_dirname;
  4760. File::Path::mkpath($dir);
  4761. }
  4762. # prefix/name1/val1/name2/val2/stdout
  4763. $outname = "$dir/stdout";
  4764. if(not open($outfhw, "+>", $outname)) {
  4765. ::error("Cannot write to `$outname'.\n");
  4766. ::wait_and_exit(255);
  4767. }
  4768. # prefix/name1/val1/name2/val2/stderr
  4769. $errname = "$dir/stderr";
  4770. if(not open($errfhw, "+>", $errname)) {
  4771. ::error("Cannot write to `$errname'.\n");
  4772. ::wait_and_exit(255);
  4773. }
  4774. $self->set_fh(1,"unlink","");
  4775. $self->set_fh(2,"unlink","");
  4776. } elsif(not $opt::ungroup) {
  4777. # To group we create temporary files for STDOUT and STDERR
  4778. # To avoid the cleanup unlink the files immediately (but keep them open)
  4779. if(@Global::tee_jobs) {
  4780. # files must be removed when the tee is done
  4781. } elsif($opt::files) {
  4782. ($outfhw, $outname) = ::tmpfile(SUFFIX => ".par");
  4783. ($errfhw, $errname) = ::tmpfile(SUFFIX => ".par");
  4784. # --files => only remove stderr
  4785. $self->set_fh(1,"unlink","");
  4786. $self->set_fh(2,"unlink",$errname);
  4787. } else {
  4788. ($outfhw, $outname) = ::tmpfile(SUFFIX => ".par");
  4789. ($errfhw, $errname) = ::tmpfile(SUFFIX => ".par");
  4790. $self->set_fh(1,"unlink",$outname);
  4791. $self->set_fh(2,"unlink",$errname);
  4792. }
  4793. } else {
  4794. # --ungroup
  4795. open($outfhw,">&",$Global::fd{1}) || die;
  4796. open($errfhw,">&",$Global::fd{2}) || die;
  4797. # File name must be empty as it will otherwise be printed
  4798. $outname = "";
  4799. $errname = "";
  4800. $self->set_fh(1,"unlink",$outname);
  4801. $self->set_fh(2,"unlink",$errname);
  4802. }
  4803. # Set writing FD
  4804. $self->set_fh(1,'w',$outfhw);
  4805. $self->set_fh(2,'w',$errfhw);
  4806. $self->set_fh(1,'name',$outname);
  4807. $self->set_fh(2,'name',$errname);
  4808. if($opt::compress) {
  4809. # Send stdout to stdin for $opt::compress_program(1)
  4810. # Send stderr to stdin for $opt::compress_program(2)
  4811. # cattail get pid: $pid = $self->fh($fdno,'rpid');
  4812. my $cattail = cattail();
  4813. for my $fdno (1,2) {
  4814. my $wpid = open(my $fdw,"|-","$opt::compress_program >>".
  4815. $self->fh($fdno,'name')) || die $?;
  4816. $self->set_fh($fdno,'w',$fdw);
  4817. $self->set_fh($fdno,'wpid',$wpid);
  4818. my $rpid = open(my $fdr, "-|", "perl", "-e", $cattail,
  4819. $opt::decompress_program, $wpid,
  4820. $self->fh($fdno,'name'),$self->fh($fdno,'unlink')) || die $?;
  4821. $self->set_fh($fdno,'r',$fdr);
  4822. $self->set_fh($fdno,'rpid',$rpid);
  4823. }
  4824. } elsif(not $opt::ungroup) {
  4825. # Set reading FD if using --group (--ungroup does not need)
  4826. for my $fdno (1,2) {
  4827. # Re-open the file for reading
  4828. # so fdw can be closed separately
  4829. # and fdr can be seeked separately (for --line-buffer)
  4830. open(my $fdr,"<", $self->fh($fdno,'name')) ||
  4831. ::die_bug("fdr: Cannot open ".$self->fh($fdno,'name'));
  4832. $self->set_fh($fdno,'r',$fdr);
  4833. # Unlink if required
  4834. $Global::debug or unlink $self->fh($fdno,"unlink");
  4835. }
  4836. }
  4837. if($opt::linebuffer) {
  4838. # Set non-blocking when using --linebuffer
  4839. $Global::use{"Fcntl"} ||= eval "use Fcntl qw(:DEFAULT :flock); 1;";
  4840. for my $fdno (1,2) {
  4841. my $fdr = $self->fh($fdno,'r');
  4842. my $flags;
  4843. fcntl($fdr, &F_GETFL, $flags) || die $!; # Get the current flags on the filehandle
  4844. $flags |= &O_NONBLOCK; # Add non-blocking to the flags
  4845. fcntl($fdr, &F_SETFL, $flags) || die $!; # Set the flags on the filehandle
  4846. }
  4847. }
  4848. }
  4849. sub max_file_name_length {
  4850. # Figure out the max length of a subdir
  4851. # TODO and the max total length
  4852. # Ext4 = 255,130816
  4853. my $testdir = shift;
  4854. my $upper = 8_000_000;
  4855. my $len = 8;
  4856. my $dir="x"x$len;
  4857. do {
  4858. rmdir($testdir."/".$dir);
  4859. $len *= 16;
  4860. $dir="x"x$len;
  4861. } while (mkdir $testdir."/".$dir);
  4862. # Then search for the actual max length between $len/16 and $len
  4863. my $min = $len/16;
  4864. my $max = $len;
  4865. while($max-$min > 5) {
  4866. # If we are within 5 chars of the exact value:
  4867. # it is not worth the extra time to find the exact value
  4868. my $test = int(($min+$max)/2);
  4869. $dir="x"x$test;
  4870. if(mkdir $testdir."/".$dir) {
  4871. rmdir($testdir."/".$dir);
  4872. $min = $test;
  4873. } else {
  4874. $max = $test;
  4875. }
  4876. }
  4877. $Global::max_file_length = $min;
  4878. return $min;
  4879. }
  4880. sub set_fh {
  4881. # Set file handle
  4882. my ($self, $fd_no, $key, $fh) = @_;
  4883. $self->{'fd'}{$fd_no,$key} = $fh;
  4884. }
  4885. sub fh {
  4886. # Get file handle
  4887. my ($self, $fd_no, $key) = @_;
  4888. return $self->{'fd'}{$fd_no,$key};
  4889. }
  4890. sub write {
  4891. my $self = shift;
  4892. my $remaining_ref = shift;
  4893. my $stdin_fh = $self->fh(0,"w");
  4894. syswrite($stdin_fh,$$remaining_ref);
  4895. }
  4896. sub set_stdin_buffer {
  4897. # Copy stdin buffer from $block_ref up to $endpos
  4898. # Prepend with $header_ref
  4899. # Remove $recstart and $recend if needed
  4900. # Input:
  4901. # $header_ref = ref to $header to prepend
  4902. # $block_ref = ref to $block to pass on
  4903. # $endpos = length of $block to pass on
  4904. # $recstart = --recstart regexp
  4905. # $recend = --recend regexp
  4906. # Returns:
  4907. # N/A
  4908. my $self = shift;
  4909. my ($header_ref,$block_ref,$endpos,$recstart,$recend) = @_;
  4910. $self->{'stdin_buffer'} = ($self->virgin() ? $$header_ref : "").substr($$block_ref,0,$endpos);
  4911. if($opt::remove_rec_sep) {
  4912. remove_rec_sep(\$self->{'stdin_buffer'},$recstart,$recend);
  4913. }
  4914. $self->{'stdin_buffer_length'} = length $self->{'stdin_buffer'};
  4915. $self->{'stdin_buffer_pos'} = 0;
  4916. }
  4917. sub stdin_buffer_length {
  4918. my $self = shift;
  4919. return $self->{'stdin_buffer_length'};
  4920. }
  4921. sub remove_rec_sep {
  4922. my ($block_ref,$recstart,$recend) = @_;
  4923. # Remove record separator
  4924. $$block_ref =~ s/$recend$recstart//gos;
  4925. $$block_ref =~ s/^$recstart//os;
  4926. $$block_ref =~ s/$recend$//os;
  4927. }
  4928. sub non_block_write {
  4929. my $self = shift;
  4930. my $something_written = 0;
  4931. use POSIX qw(:errno_h);
  4932. # use Fcntl;
  4933. # my $flags = '';
  4934. for my $buf (substr($self->{'stdin_buffer'},$self->{'stdin_buffer_pos'})) {
  4935. my $in = $self->fh(0,"w");
  4936. # fcntl($in, F_GETFL, $flags)
  4937. # or die "Couldn't get flags for HANDLE : $!\n";
  4938. # $flags |= O_NONBLOCK;
  4939. # fcntl($in, F_SETFL, $flags)
  4940. # or die "Couldn't set flags for HANDLE: $!\n";
  4941. my $rv = syswrite($in, $buf);
  4942. if (!defined($rv) && $! == EAGAIN) {
  4943. # would block
  4944. $something_written = 0;
  4945. } elsif ($self->{'stdin_buffer_pos'}+$rv != $self->{'stdin_buffer_length'}) {
  4946. # incomplete write
  4947. # Remove the written part
  4948. $self->{'stdin_buffer_pos'} += $rv;
  4949. $something_written = $rv;
  4950. } else {
  4951. # successfully wrote everything
  4952. my $a="";
  4953. $self->set_stdin_buffer(\$a,\$a,"","");
  4954. $something_written = $rv;
  4955. }
  4956. }
  4957. ::debug("pipe", "Non-block: ", $something_written);
  4958. return $something_written;
  4959. }
  4960. sub virgin {
  4961. my $self = shift;
  4962. return $self->{'virgin'};
  4963. }
  4964. sub set_virgin {
  4965. my $self = shift;
  4966. $self->{'virgin'} = shift;
  4967. }
  4968. sub pid {
  4969. my $self = shift;
  4970. return $self->{'pid'};
  4971. }
  4972. sub set_pid {
  4973. my $self = shift;
  4974. $self->{'pid'} = shift;
  4975. }
  4976. sub starttime {
  4977. # Returns:
  4978. # UNIX-timestamp this job started
  4979. my $self = shift;
  4980. return sprintf("%.3f",$self->{'starttime'});
  4981. }
  4982. sub set_starttime {
  4983. my $self = shift;
  4984. my $starttime = shift || ::now();
  4985. $self->{'starttime'} = $starttime;
  4986. }
  4987. sub runtime {
  4988. # Returns:
  4989. # Run time in seconds
  4990. my $self = shift;
  4991. return sprintf("%.3f",int(($self->endtime() - $self->starttime())*1000)/1000);
  4992. }
  4993. sub endtime {
  4994. # Returns:
  4995. # UNIX-timestamp this job ended
  4996. # 0 if not ended yet
  4997. my $self = shift;
  4998. return ($self->{'endtime'} || 0);
  4999. }
  5000. sub set_endtime {
  5001. my $self = shift;
  5002. my $endtime = shift;
  5003. $self->{'endtime'} = $endtime;
  5004. }
  5005. sub timedout {
  5006. # Is the job timedout?
  5007. # Input:
  5008. # $delta_time = time that the job may run
  5009. # Returns:
  5010. # True or false
  5011. my $self = shift;
  5012. my $delta_time = shift;
  5013. return time > $self->{'starttime'} + $delta_time;
  5014. }
  5015. sub kill {
  5016. # Kill the job.
  5017. # Send the signals to (grand)*children and pid.
  5018. # If no signals: TERM TERM KILL
  5019. # Wait 200 ms after each TERM.
  5020. # Input:
  5021. # @signals = signals to send
  5022. my $self = shift;
  5023. my @signals = @_;
  5024. my @family_pids = $self->family_pids();
  5025. # Record this jobs as failed
  5026. $self->set_exitstatus(-1);
  5027. # Send two TERMs to give time to clean up
  5028. ::debug("run", "Kill seq ", $self->seq(), "\n");
  5029. my @send_signals = @signals || ("TERM", "TERM", "KILL");
  5030. for my $signal (@send_signals) {
  5031. my $alive = 0;
  5032. for my $pid (@family_pids) {
  5033. if(kill 0, $pid) {
  5034. # The job still running
  5035. kill $signal, $pid;
  5036. $alive = 1;
  5037. }
  5038. }
  5039. # If a signal was given as input, do not do the sleep below
  5040. @signals and next;
  5041. if($signal eq "TERM" and $alive) {
  5042. # Wait up to 200 ms between TERMs - but only if any pids are alive
  5043. my $sleep = 1;
  5044. for (my $sleepsum = 0; kill 0, $family_pids[0] and $sleepsum < 200;
  5045. $sleepsum += $sleep) {
  5046. $sleep = ::reap_usleep($sleep);
  5047. }
  5048. }
  5049. }
  5050. }
  5051. sub family_pids {
  5052. # Find the pids with this->pid as (grand)*parent
  5053. # Returns:
  5054. # @pids = pids of (grand)*children
  5055. my $self = shift;
  5056. my $pid = $self->pid();
  5057. my @pids;
  5058. my ($children_of_ref, $parent_of_ref, $name_of_ref) = ::pid_table();
  5059. my @more = ($pid);
  5060. # While more (grand)*children
  5061. while(@more) {
  5062. my @m;
  5063. push @pids, @more;
  5064. for my $parent (@more) {
  5065. if($children_of_ref->{$parent}) {
  5066. # add the children of this parent
  5067. push @m, @{$children_of_ref->{$parent}};
  5068. }
  5069. }
  5070. @more = @m;
  5071. }
  5072. return (@pids);
  5073. }
  5074. sub failed {
  5075. # return number of times failed for this $sshlogin
  5076. # Input:
  5077. # $sshlogin
  5078. # Returns:
  5079. # Number of times failed for $sshlogin
  5080. my $self = shift;
  5081. my $sshlogin = shift;
  5082. return $self->{'failed'}{$sshlogin};
  5083. }
  5084. sub failed_here {
  5085. # return number of times failed for the current $sshlogin
  5086. # Returns:
  5087. # Number of times failed for this sshlogin
  5088. my $self = shift;
  5089. return $self->{'failed'}{$self->sshlogin()};
  5090. }
  5091. sub add_failed {
  5092. # increase the number of times failed for this $sshlogin
  5093. my $self = shift;
  5094. my $sshlogin = shift;
  5095. $self->{'failed'}{$sshlogin}++;
  5096. }
  5097. sub add_failed_here {
  5098. # increase the number of times failed for the current $sshlogin
  5099. my $self = shift;
  5100. $self->{'failed'}{$self->sshlogin()}++;
  5101. }
  5102. sub reset_failed {
  5103. # increase the number of times failed for this $sshlogin
  5104. my $self = shift;
  5105. my $sshlogin = shift;
  5106. delete $self->{'failed'}{$sshlogin};
  5107. }
  5108. sub reset_failed_here {
  5109. # increase the number of times failed for this $sshlogin
  5110. my $self = shift;
  5111. delete $self->{'failed'}{$self->sshlogin()};
  5112. }
  5113. sub min_failed {
  5114. # Returns:
  5115. # the number of sshlogins this command has failed on
  5116. # the minimal number of times this command has failed
  5117. my $self = shift;
  5118. my $min_failures =
  5119. ::min(map { $self->{'failed'}{$_} } keys %{$self->{'failed'}});
  5120. my $number_of_sshlogins_failed_on = scalar keys %{$self->{'failed'}};
  5121. return ($number_of_sshlogins_failed_on,$min_failures);
  5122. }
  5123. sub total_failed {
  5124. # Returns:
  5125. # $total_failures = the number of times this command has failed
  5126. my $self = shift;
  5127. my $total_failures = 0;
  5128. for (values %{$self->{'failed'}}) {
  5129. $total_failures += $_;
  5130. }
  5131. return $total_failures;
  5132. }
  5133. sub wrapped {
  5134. # Wrap command with:
  5135. # * --shellquote
  5136. # * --nice
  5137. # * --cat
  5138. # * --fifo
  5139. # * --sshlogin
  5140. # * --pipepart (@Global::cat_partials)
  5141. # * --pipe
  5142. # * --tmux
  5143. # The ordering of the wrapping is important:
  5144. # * --nice/--cat/--fifo should be done on the remote machine
  5145. # * --pipepart/--pipe should be done on the local machine inside --tmux
  5146. # Uses:
  5147. # $Global::envvar
  5148. # $opt::shellquote
  5149. # $opt::nice
  5150. # $Global::shell
  5151. # $opt::cat
  5152. # $opt::fifo
  5153. # @Global::cat_partials
  5154. # $opt::pipe
  5155. # $opt::tmux
  5156. # Returns:
  5157. # $self->{'wrapped'} = the command wrapped with the above
  5158. my $self = shift;
  5159. if(not defined $self->{'wrapped'}) {
  5160. my $command = $Global::envvar.$self->replaced();
  5161. if($opt::shellquote) {
  5162. # Prepend echo
  5163. # and quote twice
  5164. $command = "echo " .
  5165. ::shell_quote_scalar(::shell_quote_scalar($command));
  5166. }
  5167. if($opt::nice) {
  5168. # Prepend \nice -n19 $SHELL -c
  5169. # and quote.
  5170. # The '\' before nice is needed to avoid tcsh's built-in
  5171. $command = '\nice'. " -n". $opt::nice. " ".
  5172. $Global::shell. " -c ".
  5173. ::shell_quote_scalar($command);
  5174. }
  5175. if($opt::cat) {
  5176. # Prepend 'cat > {};'
  5177. # Append '_EXIT=$?;(rm {};exit $_EXIT)'
  5178. $command =
  5179. $self->{'commandline'}->replace_placeholders(["cat > \257<\257>; "], 0, 0).
  5180. $command.
  5181. $self->{'commandline'}->replace_placeholders(
  5182. ["; _EXIT=\$?; rm \257<\257>; exit \$_EXIT"], 0, 0);
  5183. } elsif($opt::fifo) {
  5184. # Prepend 'mkfifo {}; ('
  5185. # Append ') & _PID=$!; cat > {}; wait $_PID; _EXIT=$?;(rm {};exit $_EXIT)'
  5186. $command =
  5187. $self->{'commandline'}->replace_placeholders(["mkfifo \257<\257>; ("], 0, 0).
  5188. $command.
  5189. $self->{'commandline'}->replace_placeholders([") & _PID=\$!; cat > \257<\257>; ",
  5190. "wait \$_PID; _EXIT=\$?; ",
  5191. "rm \257<\257>; exit \$_EXIT"],
  5192. 0,0);
  5193. }
  5194. # Wrap with ssh + tranferring of files
  5195. $command = $self->sshlogin_wrap($command);
  5196. if(@Global::cat_partials) {
  5197. # Prepend:
  5198. # < /tmp/foo perl -e 'while(@ARGV) { sysseek(STDIN,shift,0) || die; $left = shift; while($read = sysread(STDIN,$buf, ($left > 32768 ? 32768 : $left))){ $left -= $read; syswrite(STDOUT,$buf); } }' 0 0 0 11 |
  5199. $command = (shift @Global::cat_partials). "|". "(". $command. ")";
  5200. } elsif($opt::pipe) {
  5201. # Prepend EOF-detector to avoid starting $command if EOF.
  5202. # The $tmpfile might exist if run on a remote system - we accept that risk
  5203. my ($dummy_fh, $tmpfile) = ::tmpfile(SUFFIX => ".chr");
  5204. # Unlink to avoid leaving files if --dry-run or --sshlogin
  5205. unlink $tmpfile;
  5206. $command =
  5207. # Exit value:
  5208. # empty input = true
  5209. # some input = exit val from command
  5210. qq{ sh -c 'dd bs=1 count=1 of=$tmpfile 2>/dev/null'; }.
  5211. qq{ test \! -s "$tmpfile" && rm -f "$tmpfile" && exec true; }.
  5212. qq{ (cat $tmpfile; rm $tmpfile; cat - ) | }.
  5213. "($command);";
  5214. }
  5215. if($opt::tmux) {
  5216. # Wrap command with 'tmux'
  5217. $command = $self->tmux_wrap($command);
  5218. }
  5219. $self->{'wrapped'} = $command;
  5220. }
  5221. return $self->{'wrapped'};
  5222. }
  5223. sub set_sshlogin {
  5224. my $self = shift;
  5225. my $sshlogin = shift;
  5226. $self->{'sshlogin'} = $sshlogin;
  5227. delete $self->{'sshlogin_wrap'}; # If sshlogin is changed the wrap is wrong
  5228. delete $self->{'wrapped'};
  5229. }
  5230. sub sshlogin {
  5231. my $self = shift;
  5232. return $self->{'sshlogin'};
  5233. }
  5234. sub sshlogin_wrap {
  5235. # Wrap the command with the commands needed to run remotely
  5236. # Returns:
  5237. # $self->{'sshlogin_wrap'} = command wrapped with ssh+transfer commands
  5238. my $self = shift;
  5239. my $command = shift;
  5240. if(not defined $self->{'sshlogin_wrap'}) {
  5241. my $sshlogin = $self->sshlogin();
  5242. my $sshcmd = $sshlogin->sshcommand();
  5243. my $serverlogin = $sshlogin->serverlogin();
  5244. my ($pre,$post,$cleanup)=("","","");
  5245. if($serverlogin eq ":") {
  5246. # No transfer neeeded
  5247. $self->{'sshlogin_wrap'} = $command;
  5248. } else {
  5249. # --transfer
  5250. $pre .= $self->sshtransfer();
  5251. # --return
  5252. $post .= $self->sshreturn();
  5253. # --cleanup
  5254. $post .= $self->sshcleanup();
  5255. if($post) {
  5256. # We need to save the exit status of the job
  5257. $post = '_EXIT_status=$?; ' . $post . ' exit $_EXIT_status;';
  5258. }
  5259. # If the remote login shell is (t)csh then use 'setenv'
  5260. # otherwise use 'export'
  5261. # We cannot use parse_env_var(), as PARALLEL_SEQ changes
  5262. # for each command
  5263. my $parallel_env =
  5264. ($Global::envwarn
  5265. . q{ 'eval `echo $SHELL | grep "/t\\{0,1\\}csh" > /dev/null }
  5266. . q{ && echo setenv PARALLEL_SEQ '$PARALLEL_SEQ'\; }
  5267. . q{ setenv PARALLEL_PID '$PARALLEL_PID' }
  5268. . q{ || echo PARALLEL_SEQ='$PARALLEL_SEQ'\;export PARALLEL_SEQ\; }
  5269. . q{ PARALLEL_PID='$PARALLEL_PID'\;export PARALLEL_PID` ;' });
  5270. my $remote_pre = "";
  5271. my $ssh_options = "";
  5272. if(($opt::pipe or $opt::pipepart) and $opt::ctrlc
  5273. or
  5274. not ($opt::pipe or $opt::pipepart) and not $opt::noctrlc) {
  5275. # TODO Determine if this is needed
  5276. # Propagating CTRL-C to kill remote jobs requires
  5277. # remote jobs to be run with a terminal.
  5278. $ssh_options = "-tt -oLogLevel=quiet";
  5279. # $ssh_options = "";
  5280. # tty - check if we have a tty.
  5281. # stty:
  5282. # -onlcr - make output 8-bit clean
  5283. # isig - pass CTRL-C as signal
  5284. # -echo - do not echo input
  5285. $remote_pre .= ::shell_quote_scalar('tty >/dev/null && stty isig -onlcr -echo;');
  5286. }
  5287. if($opt::workdir) {
  5288. my $wd = ::shell_quote_file($self->workdir());
  5289. $remote_pre .= ::shell_quote_scalar("mkdir -p ") . $wd .
  5290. ::shell_quote_scalar("; cd ") . $wd .
  5291. # exit 255 (instead of exec false) would be the correct thing,
  5292. # but that fails on tcsh
  5293. ::shell_quote_scalar(qq{ || exec false;});
  5294. }
  5295. # This script is to solve the problem of
  5296. # * not mixing STDERR and STDOUT
  5297. # * terminating with ctrl-c
  5298. # It works on Linux but not Solaris
  5299. # Finishes on Solaris, but wrong exit code:
  5300. # $SIG{CHLD} = sub {exit ($?&127 ? 128+($?&127) : 1+$?>>8)};
  5301. # Hangs on Solaris, but correct exit code on Linux:
  5302. # $SIG{CHLD} = sub { $done = 1 };
  5303. # $p->poll;
  5304. my $signal_script = "perl -e '".
  5305. q{
  5306. use IO::Poll;
  5307. $SIG{CHLD} = sub { $done = 1 };
  5308. $p = IO::Poll->new;
  5309. $p->mask(STDOUT, POLLHUP);
  5310. $pid=fork; unless($pid) {setpgrp; exec $ENV{SHELL}, "-c", @ARGV; die "exec: $!\n"}
  5311. $p->poll;
  5312. kill SIGHUP, -${pid} unless $done;
  5313. wait; exit ($?&127 ? 128+($?&127) : 1+$?>>8)
  5314. } . "' ";
  5315. $signal_script =~ s/\s+/ /g;
  5316. $self->{'sshlogin_wrap'} =
  5317. ($pre
  5318. . "$sshcmd $ssh_options $serverlogin $parallel_env "
  5319. . $remote_pre
  5320. # . ::shell_quote_scalar($signal_script . ::shell_quote_scalar($command))
  5321. . ::shell_quote_scalar($command)
  5322. . ";"
  5323. . $post);
  5324. }
  5325. }
  5326. return $self->{'sshlogin_wrap'};
  5327. }
  5328. sub transfer {
  5329. # Files to transfer
  5330. # Returns:
  5331. # @transfer - File names of files to transfer
  5332. my $self = shift;
  5333. my @transfer = ();
  5334. $self->{'transfersize'} = 0;
  5335. if($opt::transfer) {
  5336. for my $record (@{$self->{'commandline'}{'arg_list'}}) {
  5337. # Merge arguments from records into args
  5338. for my $arg (@$record) {
  5339. CORE::push @transfer, $arg->orig();
  5340. # filesize
  5341. if(-e $arg->orig()) {
  5342. $self->{'transfersize'} += (stat($arg->orig()))[7];
  5343. }
  5344. }
  5345. }
  5346. }
  5347. return @transfer;
  5348. }
  5349. sub transfersize {
  5350. my $self = shift;
  5351. return $self->{'transfersize'};
  5352. }
  5353. sub sshtransfer {
  5354. # Returns for each transfer file:
  5355. # rsync $file remote:$workdir
  5356. my $self = shift;
  5357. my @pre;
  5358. my $sshlogin = $self->sshlogin();
  5359. my $workdir = $self->workdir();
  5360. for my $file ($self->transfer()) {
  5361. push @pre, $sshlogin->rsync_transfer_cmd($file,$workdir).";";
  5362. }
  5363. return join("",@pre);
  5364. }
  5365. sub return {
  5366. # Files to return
  5367. # Non-quoted and with {...} substituted
  5368. # Returns:
  5369. # @non_quoted_filenames
  5370. my $self = shift;
  5371. return $self->{'commandline'}->
  5372. replace_placeholders($self->{'commandline'}{'return_files'},0,0);
  5373. }
  5374. sub returnsize {
  5375. # This is called after the job has finished
  5376. # Returns:
  5377. # $number_of_bytes transferred in return
  5378. my $self = shift;
  5379. for my $file ($self->return()) {
  5380. if(-e $file) {
  5381. $self->{'returnsize'} += (stat($file))[7];
  5382. }
  5383. }
  5384. return $self->{'returnsize'};
  5385. }
  5386. sub sshreturn {
  5387. # Returns for each return-file:
  5388. # rsync remote:$workdir/$file .
  5389. my $self = shift;
  5390. my $sshlogin = $self->sshlogin();
  5391. my $sshcmd = $sshlogin->sshcommand();
  5392. my $serverlogin = $sshlogin->serverlogin();
  5393. my $rsync_opt = "-rlDzR -e".::shell_quote_scalar($sshcmd);
  5394. my $pre = "";
  5395. for my $file ($self->return()) {
  5396. $file =~ s:^\./::g; # Remove ./ if any
  5397. my $relpath = ($file !~ m:^/:); # Is the path relative?
  5398. my $cd = "";
  5399. my $wd = "";
  5400. if($relpath) {
  5401. # rsync -avR /foo/./bar/baz.c remote:/tmp/
  5402. # == (on old systems)
  5403. # rsync -avR --rsync-path="cd /foo; rsync" remote:bar/baz.c /tmp/
  5404. $wd = ::shell_quote_file($self->workdir()."/");
  5405. }
  5406. # Only load File::Basename if actually needed
  5407. $Global::use{"File::Basename"} ||= eval "use File::Basename; 1;";
  5408. # dir/./file means relative to dir, so remove dir on remote
  5409. $file =~ m:(.*)/\./:;
  5410. my $basedir = $1 ? ::shell_quote_file($1."/") : "";
  5411. my $nobasedir = $file;
  5412. $nobasedir =~ s:.*/\./::;
  5413. $cd = ::shell_quote_file(::dirname($nobasedir));
  5414. my $rsync_cd = '--rsync-path='.::shell_quote_scalar("cd $wd$cd; rsync");
  5415. my $basename = ::shell_quote_scalar(::shell_quote_file(basename($file)));
  5416. # --return
  5417. # mkdir -p /home/tange/dir/subdir/;
  5418. # rsync (--protocol 30) -rlDzR --rsync-path="cd /home/tange/dir/subdir/; rsync"
  5419. # server:file.gz /home/tange/dir/subdir/
  5420. $pre .= "mkdir -p $basedir$cd; ".$sshlogin->rsync()." $rsync_cd $rsync_opt $serverlogin:".
  5421. $basename . " ".$basedir.$cd.";";
  5422. }
  5423. return $pre;
  5424. }
  5425. sub sshcleanup {
  5426. # Return the sshcommand needed to remove the file
  5427. # Returns:
  5428. # ssh command needed to remove files from sshlogin
  5429. my $self = shift;
  5430. my $sshlogin = $self->sshlogin();
  5431. my $sshcmd = $sshlogin->sshcommand();
  5432. my $serverlogin = $sshlogin->serverlogin();
  5433. my $workdir = $self->workdir();
  5434. my $cleancmd = "";
  5435. for my $file ($self->cleanup()) {
  5436. my @subworkdirs = parentdirs_of($file);
  5437. $cleancmd .= $sshlogin->cleanup_cmd($file,$workdir).";";
  5438. }
  5439. if(defined $opt::workdir and $opt::workdir eq "...") {
  5440. $cleancmd .= "$sshcmd $serverlogin rm -rf " . ::shell_quote_scalar($workdir).';';
  5441. }
  5442. return $cleancmd;
  5443. }
  5444. sub cleanup {
  5445. # Returns:
  5446. # Files to remove at cleanup
  5447. my $self = shift;
  5448. if($opt::cleanup) {
  5449. my @transfer = $self->transfer();
  5450. my @return = $self->return();
  5451. return (@transfer,@return);
  5452. } else {
  5453. return ();
  5454. }
  5455. }
  5456. sub workdir {
  5457. # Returns:
  5458. # the workdir on a remote machine
  5459. my $self = shift;
  5460. if(not defined $self->{'workdir'}) {
  5461. my $workdir;
  5462. if(defined $opt::workdir) {
  5463. if($opt::workdir eq ".") {
  5464. # . means current dir
  5465. my $home = $ENV{'HOME'};
  5466. eval 'use Cwd';
  5467. my $cwd = cwd();
  5468. $workdir = $cwd;
  5469. if($home) {
  5470. # If homedir exists: remove the homedir from
  5471. # workdir if cwd starts with homedir
  5472. # E.g. /home/foo/my/dir => my/dir
  5473. # E.g. /tmp/my/dir => /tmp/my/dir
  5474. my ($home_dev, $home_ino) = (stat($home))[0,1];
  5475. my $parent = "";
  5476. my @dir_parts = split(m:/:,$cwd);
  5477. my $part;
  5478. while(defined ($part = shift @dir_parts)) {
  5479. $part eq "" and next;
  5480. $parent .= "/".$part;
  5481. my ($parent_dev, $parent_ino) = (stat($parent))[0,1];
  5482. if($parent_dev == $home_dev and $parent_ino == $home_ino) {
  5483. # dev and ino is the same: We found the homedir.
  5484. $workdir = join("/",@dir_parts);
  5485. last;
  5486. }
  5487. }
  5488. }
  5489. if($workdir eq "") {
  5490. $workdir = ".";
  5491. }
  5492. } elsif($opt::workdir eq "...") {
  5493. $workdir = ".parallel/tmp/" . ::hostname() . "-" . $$
  5494. . "-" . $self->seq();
  5495. } else {
  5496. $workdir = $opt::workdir;
  5497. # Rsync treats /./ special. We don't want that
  5498. $workdir =~ s:/\./:/:g; # Remove /./
  5499. $workdir =~ s:/+$::; # Remove ending / if any
  5500. $workdir =~ s:^\./::g; # Remove starting ./ if any
  5501. }
  5502. } else {
  5503. $workdir = ".";
  5504. }
  5505. $self->{'workdir'} = ::shell_quote_scalar($workdir);
  5506. }
  5507. return $self->{'workdir'};
  5508. }
  5509. sub parentdirs_of {
  5510. # Return:
  5511. # all parentdirs except . of this dir or file - sorted desc by length
  5512. my $d = shift;
  5513. my @parents = ();
  5514. while($d =~ s:/[^/]+$::) {
  5515. if($d ne ".") {
  5516. push @parents, $d;
  5517. }
  5518. }
  5519. return @parents;
  5520. }
  5521. sub start {
  5522. # Setup STDOUT and STDERR for a job and start it.
  5523. # Returns:
  5524. # job-object or undef if job not to run
  5525. my $job = shift;
  5526. # Get the shell command to be executed (possibly with ssh infront).
  5527. my $command = $job->wrapped();
  5528. if($Global::interactive or $Global::stderr_verbose) {
  5529. if($Global::interactive) {
  5530. print $Global::original_stderr "$command ?...";
  5531. open(my $tty_fh, "<", "/dev/tty") || ::die_bug("interactive-tty");
  5532. my $answer = <$tty_fh>;
  5533. close $tty_fh;
  5534. my $run_yes = ($answer =~ /^\s*y/i);
  5535. if (not $run_yes) {
  5536. $command = "true"; # Run the command 'true'
  5537. }
  5538. } else {
  5539. print $Global::original_stderr "$command\n";
  5540. }
  5541. }
  5542. my $pid;
  5543. $job->openoutputfiles();
  5544. my($stdout_fh,$stderr_fh) = ($job->fh(1,"w"),$job->fh(2,"w"));
  5545. local (*IN,*OUT,*ERR);
  5546. open OUT, '>&', $stdout_fh or ::die_bug("Can't redirect STDOUT: $!");
  5547. open ERR, '>&', $stderr_fh or ::die_bug("Can't dup STDOUT: $!");
  5548. if(($opt::dryrun or $Global::verbose) and $opt::ungroup) {
  5549. if($Global::verbose <= 1) {
  5550. print $stdout_fh $job->replaced(),"\n";
  5551. } else {
  5552. # Verbose level > 1: Print the rsync and stuff
  5553. print $stdout_fh $command,"\n";
  5554. }
  5555. }
  5556. if($opt::dryrun) {
  5557. $command = "true";
  5558. }
  5559. $ENV{'PARALLEL_SEQ'} = $job->seq();
  5560. $ENV{'PARALLEL_PID'} = $$;
  5561. ::debug("run", $Global::total_running, " processes . Starting (",
  5562. $job->seq(), "): $command\n");
  5563. if($opt::pipe) {
  5564. my ($stdin_fh);
  5565. # The eval is needed to catch exception from open3
  5566. eval {
  5567. $pid = ::open3($stdin_fh, ">&OUT", ">&ERR", $Global::shell, "-c", $command) ||
  5568. ::die_bug("open3-pipe");
  5569. 1;
  5570. };
  5571. $job->set_fh(0,"w",$stdin_fh);
  5572. } elsif(@opt::a and not $Global::stdin_in_opt_a and $job->seq() == 1
  5573. and $job->sshlogin()->string() eq ":") {
  5574. # Give STDIN to the first job if using -a (but only if running
  5575. # locally - otherwise CTRL-C does not work for other jobs Bug#36585)
  5576. *IN = *STDIN;
  5577. # The eval is needed to catch exception from open3
  5578. eval {
  5579. $pid = ::open3("<&IN", ">&OUT", ">&ERR", $Global::shell, "-c", $command) ||
  5580. ::die_bug("open3-a");
  5581. 1;
  5582. };
  5583. # Re-open to avoid complaining
  5584. open(STDIN, "<&", $Global::original_stdin)
  5585. or ::die_bug("dup-\$Global::original_stdin: $!");
  5586. } elsif ($opt::tty and not $Global::tty_taken and -c "/dev/tty" and
  5587. open(my $devtty_fh, "<", "/dev/tty")) {
  5588. # Give /dev/tty to the command if no one else is using it
  5589. *IN = $devtty_fh;
  5590. # The eval is needed to catch exception from open3
  5591. eval {
  5592. $pid = ::open3("<&IN", ">&OUT", ">&ERR", $Global::shell, "-c", $command) ||
  5593. ::die_bug("open3-/dev/tty");
  5594. $Global::tty_taken = $pid;
  5595. close $devtty_fh;
  5596. 1;
  5597. };
  5598. } else {
  5599. # The eval is needed to catch exception from open3
  5600. eval {
  5601. $pid = ::open3(::gensym, ">&OUT", ">&ERR", $Global::shell, "-c", $command) ||
  5602. ::die_bug("open3-gensym");
  5603. 1;
  5604. };
  5605. }
  5606. if($pid) {
  5607. # A job was started
  5608. $Global::total_running++;
  5609. $Global::total_started++;
  5610. $job->set_pid($pid);
  5611. $job->set_starttime();
  5612. $Global::running{$job->pid()} = $job;
  5613. if($opt::timeout) {
  5614. $Global::timeoutq->insert($job);
  5615. }
  5616. $Global::newest_job = $job;
  5617. $Global::newest_starttime = ::now();
  5618. return $job;
  5619. } else {
  5620. # No more processes
  5621. ::debug("run", "Cannot spawn more jobs.\n");
  5622. return undef;
  5623. }
  5624. }
  5625. sub tmux_wrap {
  5626. # Wrap command with tmux for session pPID
  5627. # Input:
  5628. # $actual_command = the actual command being run (incl ssh wrap)
  5629. my $self = shift;
  5630. my $actual_command = shift;
  5631. # Temporary file name. Used for fifo to communicate exit val
  5632. my ($fh, $tmpfile) = ::tmpfile(SUFFIX => ".tmx");
  5633. $Global::unlink{$tmpfile}=1;
  5634. close $fh;
  5635. unlink $tmpfile;
  5636. my $visual_command = $self->replaced();
  5637. my $title = $visual_command;
  5638. # ; causes problems
  5639. # ascii 194-245 annoys tmux
  5640. $title =~ tr/[\011-\016;\302-\365]//d;
  5641. my $tmux;
  5642. if($Global::total_running == 0) {
  5643. $tmux = "tmux new-session -s p$$ -d -n ".
  5644. ::shell_quote_scalar($title);
  5645. print $Global::original_stderr "See output with: tmux attach -t p$$\n";
  5646. } else {
  5647. $tmux = "tmux new-window -t p$$ -n ".::shell_quote_scalar($title);
  5648. }
  5649. return "mkfifo $tmpfile; $tmux ".
  5650. # Run in tmux
  5651. ::shell_quote_scalar(
  5652. "(".$actual_command.');(echo $?$status;echo 255) >'.$tmpfile."&".
  5653. "echo ".::shell_quote_scalar($visual_command).";".
  5654. "echo \007Job finished at: `date`;sleep 10").
  5655. # Run outside tmux
  5656. # Read the first line from the fifo and use that as status code
  5657. "; exit `perl -ne 'unlink \$ARGV; 1..1 and print' $tmpfile` ";
  5658. }
  5659. sub is_already_in_results {
  5660. # Do we already have results for this job?
  5661. # Returns:
  5662. # $job_already_run = bool whether there is output for this or not
  5663. my $job = $_[0];
  5664. my $args_as_dirname = $job->{'commandline'}->args_as_dirname();
  5665. # prefix/name1/val1/name2/val2/
  5666. my $dir = $opt::results."/".$args_as_dirname;
  5667. ::debug("run", "Test $dir/stdout", -e "$dir/stdout", "\n");
  5668. return -e "$dir/stdout";
  5669. }
  5670. sub is_already_in_joblog {
  5671. my $job = shift;
  5672. return vec($Global::job_already_run,$job->seq(),1);
  5673. }
  5674. sub set_job_in_joblog {
  5675. my $job = shift;
  5676. vec($Global::job_already_run,$job->seq(),1) = 1;
  5677. }
  5678. sub should_be_retried {
  5679. # Should this job be retried?
  5680. # Returns
  5681. # 0 - do not retry
  5682. # 1 - job queued for retry
  5683. my $self = shift;
  5684. if (not $opt::retries) {
  5685. return 0;
  5686. }
  5687. if(not $self->exitstatus()) {
  5688. # Completed with success. If there is a recorded failure: forget it
  5689. $self->reset_failed_here();
  5690. return 0
  5691. } else {
  5692. # The job failed. Should it be retried?
  5693. $self->add_failed_here();
  5694. if($self->total_failed() == $opt::retries) {
  5695. # This has been retried enough
  5696. return 0;
  5697. } else {
  5698. # This command should be retried
  5699. $self->set_endtime(undef);
  5700. $Global::JobQueue->unget($self);
  5701. ::debug("run", "Retry ", $self->seq(), "\n");
  5702. return 1;
  5703. }
  5704. }
  5705. }
  5706. sub print {
  5707. # Print the output of the jobs
  5708. # Returns: N/A
  5709. my $self = shift;
  5710. ::debug("print", ">>joboutput ", $self->replaced(), "\n");
  5711. if($opt::dryrun) {
  5712. # Nothing was printed to this job:
  5713. # cleanup tmp files if --files was set
  5714. unlink $self->fh(1,"name");
  5715. }
  5716. if($opt::pipe and $self->virgin()) {
  5717. # Skip --joblog, --dryrun, --verbose
  5718. } else {
  5719. if($Global::joblog and defined $self->{'exitstatus'}) {
  5720. # Add to joblog when finished
  5721. $self->print_joblog();
  5722. }
  5723. # Printing is only relevant for grouped/--line-buffer output.
  5724. $opt::ungroup and return;
  5725. # Check for disk full
  5726. exit_if_disk_full();
  5727. if(($opt::dryrun or $Global::verbose)
  5728. and
  5729. not $self->{'verbose_printed'}) {
  5730. $self->{'verbose_printed'}++;
  5731. if($Global::verbose <= 1) {
  5732. print STDOUT $self->replaced(),"\n";
  5733. } else {
  5734. # Verbose level > 1: Print the rsync and stuff
  5735. print STDOUT $self->wrapped(),"\n";
  5736. }
  5737. # If STDOUT and STDERR are merged,
  5738. # we want the command to be printed first
  5739. # so flush to avoid STDOUT being buffered
  5740. flush STDOUT;
  5741. }
  5742. }
  5743. for my $fdno (sort { $a <=> $b } keys %Global::fd) {
  5744. # Sort by file descriptor numerically: 1,2,3,..,9,10,11
  5745. $fdno == 0 and next;
  5746. my $out_fd = $Global::fd{$fdno};
  5747. my $in_fh = $self->fh($fdno,"r");
  5748. if(not $in_fh) {
  5749. if(not $Job::file_descriptor_warning_printed{$fdno}++) {
  5750. # ::warning("File descriptor $fdno not defined\n");
  5751. }
  5752. next;
  5753. }
  5754. ::debug("print", "File descriptor $fdno (", $self->fh($fdno,"name"), "):");
  5755. if($opt::files) {
  5756. # If --compress: $in_fh must be closed first.
  5757. close $self->fh($fdno,"w");
  5758. close $in_fh;
  5759. if($opt::pipe and $self->virgin()) {
  5760. # Nothing was printed to this job:
  5761. # cleanup unused tmp files if --files was set
  5762. for my $fdno (1,2) {
  5763. unlink $self->fh($fdno,"name");
  5764. unlink $self->fh($fdno,"unlink");
  5765. }
  5766. } elsif($fdno == 1 and $self->fh($fdno,"name")) {
  5767. print $out_fd $self->fh($fdno,"name"),"\n";
  5768. }
  5769. } elsif($opt::linebuffer) {
  5770. # Line buffered print out
  5771. $self->linebuffer_print($fdno,$in_fh,$out_fd);
  5772. } else {
  5773. my $buf;
  5774. close $self->fh($fdno,"w");
  5775. seek $in_fh, 0, 0;
  5776. # $in_fh is now ready for reading at position 0
  5777. if($opt::tag or defined $opt::tagstring) {
  5778. my $tag = $self->tag();
  5779. if($fdno == 2) {
  5780. # OpenSSH_3.6.1p2 gives 'tcgetattr: Invalid argument' with -tt
  5781. # This is a crappy way of ignoring it.
  5782. while(<$in_fh>) {
  5783. if(/^(client_process_control: )?tcgetattr: Invalid argument\n/) {
  5784. # Skip
  5785. } else {
  5786. print $out_fd $tag,$_;
  5787. }
  5788. # At most run the loop once
  5789. last;
  5790. }
  5791. }
  5792. while(<$in_fh>) {
  5793. print $out_fd $tag,$_;
  5794. }
  5795. } else {
  5796. my $buf;
  5797. if($fdno == 2) {
  5798. # OpenSSH_3.6.1p2 gives 'tcgetattr: Invalid argument' with -tt
  5799. # This is a crappy way of ignoring it.
  5800. sysread($in_fh,$buf,1_000);
  5801. $buf =~ s/^(client_process_control: )?tcgetattr: Invalid argument\n//;
  5802. print $out_fd $buf;
  5803. }
  5804. while(sysread($in_fh,$buf,32768)) {
  5805. print $out_fd $buf;
  5806. }
  5807. }
  5808. close $in_fh;
  5809. }
  5810. flush $out_fd;
  5811. }
  5812. ::debug("print", "<<joboutput @command\n");
  5813. }
  5814. sub linebuffer_print {
  5815. my $self = shift;
  5816. my ($fdno,$in_fh,$out_fd) = @_;
  5817. my $partial = \$self->{'partial_line',$fdno};
  5818. if(defined $self->{'exitstatus'}) {
  5819. # If the job is dead: close printing fh. Needed for --compress
  5820. close $self->fh($fdno,"w");
  5821. if($opt::compress) {
  5822. # Blocked reading in final round
  5823. $Global::use{"Fcntl"} ||= eval "use Fcntl qw(:DEFAULT :flock); 1;";
  5824. for my $fdno (1,2) {
  5825. my $fdr = $self->fh($fdno,'r');
  5826. my $flags;
  5827. fcntl($fdr, &F_GETFL, $flags) || die $!; # Get the current flags on the filehandle
  5828. $flags &= ~&O_NONBLOCK; # Remove non-blocking to the flags
  5829. fcntl($fdr, &F_SETFL, $flags) || die $!; # Set the flags on the filehandle
  5830. }
  5831. }
  5832. }
  5833. # This seek will clear EOF
  5834. seek $in_fh, tell($in_fh), 0;
  5835. # The read is non-blocking: The $in_fh is set to non-blocking.
  5836. # 32768 --tag = 5.1s
  5837. # 327680 --tag = 4.4s
  5838. # 1024000 --tag = 4.4s
  5839. # 3276800 --tag = 4.3s
  5840. # 32768000 --tag = 4.7s
  5841. # 10240000 --tag = 4.3s
  5842. while(read($in_fh,substr($$partial,length $$partial),3276800)) {
  5843. # Append to $$partial
  5844. # Find the last \n
  5845. my $i = rindex($$partial,"\n");
  5846. if($i != -1) {
  5847. # One or more complete lines were found
  5848. if($fdno == 2 and not $self->{'printed_first_line',$fdno}++) {
  5849. # OpenSSH_3.6.1p2 gives 'tcgetattr: Invalid argument' with -tt
  5850. # This is a crappy way of ignoring it.
  5851. $$partial =~ s/^(client_process_control: )?tcgetattr: Invalid argument\n//;
  5852. # Length of partial line has changed: Find the last \n again
  5853. $i = rindex($$partial,"\n");
  5854. }
  5855. if($opt::tag or defined $opt::tagstring) {
  5856. # Replace ^ with $tag within the full line
  5857. my $tag = $self->tag();
  5858. substr($$partial,0,$i+1) =~ s/^/$tag/gm;
  5859. # Length of partial line has changed: Find the last \n again
  5860. $i = rindex($$partial,"\n");
  5861. }
  5862. # Print up to and including the last \n
  5863. print $out_fd substr($$partial,0,$i+1);
  5864. # Remove the printed part
  5865. substr($$partial,0,$i+1)="";
  5866. }
  5867. }
  5868. if(defined $self->{'exitstatus'}) {
  5869. # If the job is dead: print the remaining partial line
  5870. # read remaining
  5871. if($$partial and ($opt::tag or defined $opt::tagstring)) {
  5872. my $tag = $self->tag();
  5873. $$partial =~ s/^/$tag/gm;
  5874. }
  5875. print $out_fd $$partial;
  5876. # Release the memory
  5877. $$partial = undef;
  5878. if($self->fh($fdno,"rpid") and CORE::kill 0, $self->fh($fdno,"rpid")) {
  5879. # decompress still running
  5880. } else {
  5881. # decompress done: close fh
  5882. close $in_fh;
  5883. }
  5884. }
  5885. }
  5886. sub print_joblog {
  5887. my $self = shift;
  5888. my $cmd;
  5889. if($Global::verbose <= 1) {
  5890. $cmd = $self->replaced();
  5891. } else {
  5892. # Verbose level > 1: Print the rsync and stuff
  5893. $cmd = "@command";
  5894. }
  5895. print $Global::joblog
  5896. join("\t", $self->seq(), $self->sshlogin()->string(),
  5897. $self->starttime(), sprintf("%10.3f",$self->runtime()),
  5898. $self->transfersize(), $self->returnsize(),
  5899. $self->exitstatus(), $self->exitsignal(), $cmd
  5900. ). "\n";
  5901. flush $Global::joblog;
  5902. $self->set_job_in_joblog();
  5903. }
  5904. sub tag {
  5905. my $self = shift;
  5906. if(not defined $self->{'tag'}) {
  5907. $self->{'tag'} = $self->{'commandline'}->
  5908. replace_placeholders([$opt::tagstring],0,0)."\t";
  5909. }
  5910. return $self->{'tag'};
  5911. }
  5912. sub hostgroups {
  5913. my $self = shift;
  5914. if(not defined $self->{'hostgroups'}) {
  5915. $self->{'hostgroups'} = $self->{'commandline'}->{'arg_list'}[0][0]->{'hostgroups'};
  5916. }
  5917. return @{$self->{'hostgroups'}};
  5918. }
  5919. sub exitstatus {
  5920. my $self = shift;
  5921. return $self->{'exitstatus'};
  5922. }
  5923. sub set_exitstatus {
  5924. my $self = shift;
  5925. my $exitstatus = shift;
  5926. if($exitstatus) {
  5927. # Overwrite status if non-zero
  5928. $self->{'exitstatus'} = $exitstatus;
  5929. } else {
  5930. # Set status but do not overwrite
  5931. # Status may have been set by --timeout
  5932. $self->{'exitstatus'} ||= $exitstatus;
  5933. }
  5934. }
  5935. sub exitsignal {
  5936. my $self = shift;
  5937. return $self->{'exitsignal'};
  5938. }
  5939. sub set_exitsignal {
  5940. my $self = shift;
  5941. my $exitsignal = shift;
  5942. $self->{'exitsignal'} = $exitsignal;
  5943. }
  5944. {
  5945. my ($disk_full_fh, $b8193, $name);
  5946. sub exit_if_disk_full {
  5947. # Checks if $TMPDIR is full by writing 8kb to a tmpfile
  5948. # If the disk is full: Exit immediately.
  5949. # Returns:
  5950. # N/A
  5951. if(not $disk_full_fh) {
  5952. ($disk_full_fh, $name) = ::tmpfile(SUFFIX => ".df");
  5953. unlink $name;
  5954. $b8193 = "x"x8193;
  5955. }
  5956. # Linux does not discover if a disk is full if writing <= 8192
  5957. # Tested on:
  5958. # bfs btrfs cramfs ext2 ext3 ext4 ext4dev jffs2 jfs minix msdos
  5959. # ntfs reiserfs tmpfs ubifs vfat xfs
  5960. # TODO this should be tested on different OS similar to this:
  5961. #
  5962. # doit() {
  5963. # sudo mount /dev/ram0 /mnt/loop; sudo chmod 1777 /mnt/loop
  5964. # seq 100000 | parallel --tmpdir /mnt/loop/ true &
  5965. # seq 6900000 > /mnt/loop/i && echo seq OK
  5966. # seq 6980868 > /mnt/loop/i
  5967. # seq 10000 > /mnt/loop/ii
  5968. # sleep 3
  5969. # sudo umount /mnt/loop/ || sudo umount -l /mnt/loop/
  5970. # echo >&2
  5971. # }
  5972. print $disk_full_fh $b8193;
  5973. if(not $disk_full_fh
  5974. or
  5975. tell $disk_full_fh == 0) {
  5976. ::error("Output is incomplete. Cannot append to buffer file in $ENV{'TMPDIR'}. Is the disk full?\n");
  5977. ::error("Change \$TMPDIR with --tmpdir or use --compress.\n");
  5978. ::wait_and_exit(255);
  5979. }
  5980. truncate $disk_full_fh, 0;
  5981. seek($disk_full_fh, 0, 0) || die;
  5982. }
  5983. }
  5984. package CommandLine;
  5985. sub new {
  5986. my $class = shift;
  5987. my $seq = shift;
  5988. my $commandref = shift;
  5989. $commandref || die;
  5990. my $arg_queue = shift;
  5991. my $context_replace = shift;
  5992. my $max_number_of_args = shift; # for -N and normal (-n1)
  5993. my $return_files = shift;
  5994. my $replacecount_ref = shift;
  5995. my $len_ref = shift;
  5996. my %replacecount = %$replacecount_ref;
  5997. my %len = %$len_ref;
  5998. for (keys %$replacecount_ref) {
  5999. # Total length of this replacement string {} replaced with all args
  6000. $len{$_} = 0;
  6001. }
  6002. return bless {
  6003. 'command' => $commandref,
  6004. 'seq' => $seq,
  6005. 'len' => \%len,
  6006. 'arg_list' => [],
  6007. 'arg_queue' => $arg_queue,
  6008. 'max_number_of_args' => $max_number_of_args,
  6009. 'replacecount' => \%replacecount,
  6010. 'context_replace' => $context_replace,
  6011. 'return_files' => $return_files,
  6012. 'replaced' => undef,
  6013. }, ref($class) || $class;
  6014. }
  6015. sub seq {
  6016. my $self = shift;
  6017. return $self->{'seq'};
  6018. }
  6019. {
  6020. my $max_slot_number;
  6021. sub slot {
  6022. # Find the number of a free job slot and return it
  6023. # Uses:
  6024. # @Global::slots
  6025. # Returns:
  6026. # $jobslot = number of jobslot
  6027. my $self = shift;
  6028. if(not $self->{'slot'}) {
  6029. if(not @Global::slots) {
  6030. # $Global::max_slot_number will typically be $Global::max_jobs_running
  6031. push @Global::slots, ++$max_slot_number;
  6032. }
  6033. $self->{'slot'} = shift @Global::slots;
  6034. }
  6035. return $self->{'slot'};
  6036. }
  6037. }
  6038. sub populate {
  6039. # Add arguments from arg_queue until the number of arguments or
  6040. # max line length is reached
  6041. # Uses:
  6042. # $Global::minimal_command_line_length
  6043. # $opt::cat
  6044. # $opt::fifo
  6045. # $Global::JobQueue
  6046. # $opt::m
  6047. # $opt::X
  6048. # $CommandLine::already_spread
  6049. # $Global::max_jobs_running
  6050. # Returns: N/A
  6051. my $self = shift;
  6052. my $next_arg;
  6053. my $max_len = $Global::minimal_command_line_length || Limits::Command::max_length();
  6054. if($opt::cat or $opt::fifo) {
  6055. # Generate a tempfile name that will be used as {}
  6056. my($outfh,$name) = ::tmpfile(SUFFIX => ".pip");
  6057. close $outfh;
  6058. # Unlink is needed if: ssh otheruser@localhost
  6059. unlink $name;
  6060. $Global::JobQueue->{'commandlinequeue'}->{'arg_queue'}->unget([Arg->new($name)]);
  6061. }
  6062. while (not $self->{'arg_queue'}->empty()) {
  6063. $next_arg = $self->{'arg_queue'}->get();
  6064. if(not defined $next_arg) {
  6065. next;
  6066. }
  6067. $self->push($next_arg);
  6068. if($self->len() >= $max_len) {
  6069. # Command length is now > max_length
  6070. # If there are arguments: remove the last
  6071. # If there are no arguments: Error
  6072. # TODO stuff about -x opt_x
  6073. if($self->number_of_args() > 1) {
  6074. # There is something to work on
  6075. $self->{'arg_queue'}->unget($self->pop());
  6076. last;
  6077. } else {
  6078. my $args = join(" ", map { $_->orig() } @$next_arg);
  6079. ::error("Command line too long (",
  6080. $self->len(), " >= ",
  6081. $max_len,
  6082. ") at number ",
  6083. $self->{'arg_queue'}->arg_number(),
  6084. ": ".
  6085. (substr($args,0,50))."...\n");
  6086. $self->{'arg_queue'}->unget($self->pop());
  6087. ::wait_and_exit(255);
  6088. }
  6089. }
  6090. if(defined $self->{'max_number_of_args'}) {
  6091. if($self->number_of_args() >= $self->{'max_number_of_args'}) {
  6092. last;
  6093. }
  6094. }
  6095. }
  6096. if(($opt::m or $opt::X) and not $CommandLine::already_spread
  6097. and $self->{'arg_queue'}->empty() and $Global::max_jobs_running) {
  6098. # -m or -X and EOF => Spread the arguments over all jobslots
  6099. # (unless they are already spread)
  6100. $CommandLine::already_spread ||= 1;
  6101. if($self->number_of_args() > 1) {
  6102. $self->{'max_number_of_args'} =
  6103. ::ceil($self->number_of_args()/$Global::max_jobs_running);
  6104. $Global::JobQueue->{'commandlinequeue'}->{'max_number_of_args'} =
  6105. $self->{'max_number_of_args'};
  6106. $self->{'arg_queue'}->unget($self->pop_all());
  6107. while($self->number_of_args() < $self->{'max_number_of_args'}) {
  6108. $self->push($self->{'arg_queue'}->get());
  6109. }
  6110. }
  6111. }
  6112. }
  6113. sub push {
  6114. # Add one or more records as arguments
  6115. # Returns: N/A
  6116. my $self = shift;
  6117. my $record = shift;
  6118. push @{$self->{'arg_list'}}, $record;
  6119. my $quote_arg = $Global::noquote ? 0 : not $Global::quoting;
  6120. my $rep;
  6121. for my $arg (@$record) {
  6122. if(defined $arg) {
  6123. for my $perlexpr (keys %{$self->{'replacecount'}}) {
  6124. # 50% faster than below
  6125. $self->{'len'}{$perlexpr} += length $arg->replace($perlexpr,$quote_arg,$self);
  6126. # $rep = $arg->replace($perlexpr,$quote_arg,$self);
  6127. # $self->{'len'}{$perlexpr} += length $rep;
  6128. # ::debug("length", "Length: ", length $rep,
  6129. # "(", $perlexpr, "=>", $rep, ")\n");
  6130. }
  6131. }
  6132. }
  6133. }
  6134. sub pop {
  6135. # Remove last argument
  6136. # Returns:
  6137. # the last record
  6138. my $self = shift;
  6139. my $record = pop @{$self->{'arg_list'}};
  6140. my $quote_arg = $Global::noquote ? 0 : not $Global::quoting;
  6141. for my $arg (@$record) {
  6142. if(defined $arg) {
  6143. for my $perlexpr (keys %{$self->{'replacecount'}}) {
  6144. $self->{'len'}{$perlexpr} -=
  6145. length $arg->replace($perlexpr,$quote_arg,$self);
  6146. }
  6147. }
  6148. }
  6149. return $record;
  6150. }
  6151. sub pop_all {
  6152. # Remove all arguments and zeros the length of replacement strings
  6153. # Returns:
  6154. # all records
  6155. my $self = shift;
  6156. my @popped = @{$self->{'arg_list'}};
  6157. for my $replacement_string (keys %{$self->{'replacecount'}}) {
  6158. $self->{'len'}{$replacement_string} = 0;
  6159. }
  6160. $self->{'arg_list'} = [];
  6161. return @popped;
  6162. }
  6163. sub number_of_args {
  6164. # The number of records
  6165. # Returns:
  6166. # number of records
  6167. my $self = shift;
  6168. # Ftq rudef oaawuq ime dqxqmeqp az 2011-01-24 mzp ime iaz nk MQhmd
  6169. # Mdzrvadp Nvmdymeaz az 2011-04-10. Ftue oaawuq dqxqmeqp az
  6170. # 2013-08-18 ue m nuf tmdpqd me kag tmhq fa geq daf14. Bxqmeq
  6171. # qymux oaawuq@fmzsq.pw itqz kag dqmp ftue.
  6172. #
  6173. # U my ftq ymuzfmuzqd ar m buqoq ar rdqq earfimdq omxxqp SZG
  6174. # Bmdmxxqx. Rdqq earfimdq sgmdmzfqqe kag mooqee fa ftq eagdoq
  6175. # oapq, ngf U tmhq nqqz iazpqduzs tai ymzk mofgmxxk _dqmp_ ftq
  6176. # eagdoq oapq.
  6177. #
  6178. # Fa fqef ftue U bgf uz m oayyqzf fqxxuzs bqabxq fa qymux yq itqz
  6179. # ftqk dqmp ftue. Ftq oayyqzf ime bgf uz m eqofuaz ar ftq oapq
  6180. # ftmf za azq iagxp xaaw fa ruj ad uybdahq ftq earfimdq - ea ftq
  6181. # eagdoq oapq qcguhmxqzf fa m pgefk oadzqd. Fa ymwq egdq ftq
  6182. # oayyqzf iagxp zaf etai gb ur eayq azq vgef sdqbbqp ftdagst ftq
  6183. # eagdoq oapq U daf13'qp ftq eagdoq oapq
  6184. # tffb://qz.iuwubqpum.ads/iuwu/DAF13
  6185. #
  6186. # 2.5 yazfte xmfqd U dqoquhqp mz qymux rday eayqazq ita zaf azxk
  6187. # ymzmsqp fa ruzp ftq oayyqzf, ngf mxea ymzmsqp fa sgqee ftq oapq
  6188. # tmp fa nq daf13'qp.
  6189. #
  6190. # Ftue nduzse yq fa ftq oazoxgeuaz ftmf ftqdq _mdq_ bqabxq, ita
  6191. # mdq zaf mrruxumfqp iuft ftq bdavqof, ftmf iuxx dqmp ftq eagdoq
  6192. # oapq - ftagst uf ymk zaf tmbbqz hqdk arfqz.
  6193. #
  6194. # This is really the number of records
  6195. return $#{$self->{'arg_list'}}+1;
  6196. }
  6197. sub number_of_recargs {
  6198. # The number of args in records
  6199. # Returns:
  6200. # number of args records
  6201. my $self = shift;
  6202. my $sum = 0;
  6203. my $nrec = scalar @{$self->{'arg_list'}};
  6204. if($nrec) {
  6205. $sum = $nrec * (scalar @{$self->{'arg_list'}[0]});
  6206. }
  6207. return $sum;
  6208. }
  6209. sub args_as_string {
  6210. # Returns:
  6211. # all unmodified arguments joined with ' ' (similar to {})
  6212. my $self = shift;
  6213. return (join " ", map { $_->orig() }
  6214. map { @$_ } @{$self->{'arg_list'}});
  6215. }
  6216. sub args_as_dirname {
  6217. # Returns:
  6218. # all unmodified arguments joined with '/' (similar to {})
  6219. # \t \0 \\ and / are quoted as: \t \0 \\ \_
  6220. # If $Global::max_file_length: Keep subdirs < $Global::max_file_length
  6221. my $self = shift;
  6222. my @res = ();
  6223. for my $rec_ref (@{$self->{'arg_list'}}) {
  6224. # If headers are used, sort by them.
  6225. # Otherwise keep the order from the command line.
  6226. my @header_indexes_sorted = header_indexes_sorted($#$rec_ref+1);
  6227. for my $n (@header_indexes_sorted) {
  6228. CORE::push(@res,
  6229. $Global::input_source_header{$n},
  6230. map { my $s = $_;
  6231. # \t \0 \\ and / are quoted as: \t \0 \\ \_
  6232. $s =~ s/\\/\\\\/g;
  6233. $s =~ s/\t/\\t/g;
  6234. $s =~ s/\0/\\0/g;
  6235. $s =~ s:/:\\_:g;
  6236. if($Global::max_file_length) {
  6237. # Keep each subdir shorter than the longest
  6238. # allowed file name
  6239. $s = substr($s,0,$Global::max_file_length);
  6240. }
  6241. $s; }
  6242. $rec_ref->[$n-1]->orig());
  6243. }
  6244. }
  6245. return join "/", @res;
  6246. }
  6247. sub header_indexes_sorted {
  6248. # Sort headers first by number then by name.
  6249. # E.g.: 1a 1b 11a 11b
  6250. # Returns:
  6251. # Indexes of %Global::input_source_header sorted
  6252. my $max_col = shift;
  6253. no warnings 'numeric';
  6254. for my $col (1 .. $max_col) {
  6255. # Make sure the header is defined. If it is not: use column number
  6256. if(not defined $Global::input_source_header{$col}) {
  6257. $Global::input_source_header{$col} = $col;
  6258. }
  6259. }
  6260. my @header_indexes_sorted = sort {
  6261. # Sort headers numerically then asciibetically
  6262. $Global::input_source_header{$a} <=> $Global::input_source_header{$b}
  6263. or
  6264. $Global::input_source_header{$a} cmp $Global::input_source_header{$b}
  6265. } 1 .. $max_col;
  6266. return @header_indexes_sorted;
  6267. }
  6268. sub len {
  6269. # Uses:
  6270. # $opt::shellquote
  6271. # The length of the command line with args substituted
  6272. my $self = shift;
  6273. my $len = 0;
  6274. # Add length of the original command with no args
  6275. # Length of command w/ all replacement args removed
  6276. $len += $self->{'len'}{'noncontext'} + @{$self->{'command'}} -1;
  6277. ::debug("length", "noncontext + command: $len\n");
  6278. my $recargs = $self->number_of_recargs();
  6279. if($self->{'context_replace'}) {
  6280. # Context is duplicated for each arg
  6281. $len += $recargs * $self->{'len'}{'context'};
  6282. for my $replstring (keys %{$self->{'replacecount'}}) {
  6283. # If the replacements string is more than once: mulitply its length
  6284. $len += $self->{'len'}{$replstring} *
  6285. $self->{'replacecount'}{$replstring};
  6286. ::debug("length", $replstring, " ", $self->{'len'}{$replstring}, "*",
  6287. $self->{'replacecount'}{$replstring}, "\n");
  6288. }
  6289. # echo 11 22 33 44 55 66 77 88 99 1010
  6290. # echo 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
  6291. # 5 + ctxgrp*arg
  6292. ::debug("length", "Ctxgrp: ", $self->{'len'}{'contextgroups'},
  6293. " Groups: ", $self->{'len'}{'noncontextgroups'}, "\n");
  6294. # Add space between context groups
  6295. $len += ($recargs-1) * ($self->{'len'}{'contextgroups'});
  6296. } else {
  6297. # Each replacement string may occur several times
  6298. # Add the length for each time
  6299. $len += 1*$self->{'len'}{'context'};
  6300. ::debug("length", "context+noncontext + command: $len\n");
  6301. for my $replstring (keys %{$self->{'replacecount'}}) {
  6302. # (space between regargs + length of replacement)
  6303. # * number this replacement is used
  6304. $len += ($recargs -1 + $self->{'len'}{$replstring}) *
  6305. $self->{'replacecount'}{$replstring};
  6306. }
  6307. }
  6308. if($opt::nice) {
  6309. # Pessimistic length if --nice is set
  6310. # Worse than worst case: every char needs to be quoted with \
  6311. $len *= 2;
  6312. }
  6313. if($Global::quoting) {
  6314. # Pessimistic length if -q is set
  6315. # Worse than worst case: every char needs to be quoted with \
  6316. $len *= 2;
  6317. }
  6318. if($opt::shellquote) {
  6319. # Pessimistic length if --shellquote is set
  6320. # Worse than worst case: every char needs to be quoted with \ twice
  6321. $len *= 4;
  6322. }
  6323. # If we are using --env, add the prefix for that, too.
  6324. $len += $Global::envvarlen;
  6325. return $len;
  6326. }
  6327. sub replaced {
  6328. # Uses:
  6329. # $Global::noquote
  6330. # $Global::quoting
  6331. # Returns:
  6332. # $replaced = command with place holders replaced and prepended
  6333. my $self = shift;
  6334. if(not defined $self->{'replaced'}) {
  6335. # Don't quote arguments if the input is the full command line
  6336. my $quote_arg = $Global::noquote ? 0 : not $Global::quoting;
  6337. $self->{'replaced'} = $self->replace_placeholders($self->{'command'},$Global::quoting,$quote_arg);
  6338. my $len = length $self->{'replaced'};
  6339. if ($len != $self->len()) {
  6340. ::debug("length", $len, " != ", $self->len(), " ", $self->{'replaced'}, "\n");
  6341. } else {
  6342. ::debug("length", $len, " == ", $self->len(), " ", $self->{'replaced'}, "\n");
  6343. }
  6344. }
  6345. return $self->{'replaced'};
  6346. }
  6347. sub replace_placeholders {
  6348. # Replace foo{}bar with fooargbar
  6349. # Input:
  6350. # $targetref = command as shell words
  6351. # $quote = should everything be quoted?
  6352. # $quote_arg = should replaced arguments be quoted?
  6353. # Returns:
  6354. # @target with placeholders replaced
  6355. my $self = shift;
  6356. my $targetref = shift;
  6357. my $quote = shift;
  6358. my $quote_arg = shift;
  6359. my $context_replace = $self->{'context_replace'};
  6360. my @target = @$targetref;
  6361. ::debug("replace", "Replace @target\n");
  6362. # -X = context replace
  6363. # maybe multiple input sources
  6364. # maybe --xapply
  6365. if(not @target) {
  6366. # @target is empty: Return empty array
  6367. return @target;
  6368. }
  6369. # Fish out the words that have replacement strings in them
  6370. my %word;
  6371. for (@target) {
  6372. my $tt = $_;
  6373. ::debug("replace", "Target: $tt");
  6374. # a{1}b{}c{}d
  6375. # a{=1 $_=$_ =}b{= $_=$_ =}c{= $_=$_ =}d
  6376. # a\257<1 $_=$_ \257>b\257< $_=$_ \257>c\257< $_=$_ \257>d
  6377. # A B C => aAbA B CcA B Cd
  6378. # -X A B C => aAbAcAd aAbBcBd aAbCcCd
  6379. if($context_replace) {
  6380. while($tt =~ s/([^\s\257]* # before {=
  6381. (?:
  6382. \257< # {=
  6383. [^\257]*? # The perl expression
  6384. \257> # =}
  6385. [^\s\257]* # after =}
  6386. )+)/ /x) {
  6387. # $1 = pre \257 perlexpr \257 post
  6388. $word{"$1"} ||= 1;
  6389. }
  6390. } else {
  6391. while($tt =~ s/( (?: \257<([^\257]*?)\257>) )//x) {
  6392. # $f = \257 perlexpr \257
  6393. $word{$1} ||= 1;
  6394. }
  6395. }
  6396. }
  6397. my @word = keys %word;
  6398. my %replace;
  6399. my @arg;
  6400. for my $record (@{$self->{'arg_list'}}) {
  6401. # $self->{'arg_list'} = [ [Arg11, Arg12], [Arg21, Arg22], [Arg31, Arg32] ]
  6402. # Merge arg-objects from records into @arg for easy access
  6403. CORE::push @arg, @$record;
  6404. }
  6405. # Add one arg if empty to allow {#} and {%} to be computed only once
  6406. if(not @arg) { @arg = (Arg->new("")); }
  6407. # Number of arguments - used for positional arguments
  6408. my $n = $#_+1;
  6409. # This is actually a CommandLine-object,
  6410. # but it looks nice to be able to say {= $job->slot() =}
  6411. my $job = $self;
  6412. for my $word (@word) {
  6413. # word = AB \257< perlexpr \257> CD \257< perlexpr \257> EF
  6414. my $w = $word;
  6415. ::debug("replace", "Replacing in $w\n");
  6416. # Replace positional arguments
  6417. $w =~ s< ([^\s\257]*) # before {=
  6418. \257< # {=
  6419. (-?\d+) # Position (eg. -2 or 3)
  6420. ([^\257]*?) # The perl expression
  6421. \257> # =}
  6422. ([^\s\257]*) # after =}
  6423. >
  6424. { $1. # Context (pre)
  6425. (
  6426. $arg[$2 > 0 ? $2-1 : $n+$2] ? # If defined: replace
  6427. $arg[$2 > 0 ? $2-1 : $n+$2]->replace($3,$quote_arg,$self)
  6428. : "")
  6429. .$4 }egx;# Context (post)
  6430. ::debug("replace", "Positional replaced $word with: $w\n");
  6431. if($w !~ /\257/) {
  6432. # No more replacement strings in $w: No need to do more
  6433. if($quote) {
  6434. CORE::push(@{$replace{::shell_quote($word)}}, $w);
  6435. } else {
  6436. CORE::push(@{$replace{$word}}, $w);
  6437. }
  6438. next;
  6439. }
  6440. # for each arg:
  6441. # compute replacement for each string
  6442. # replace replacement strings with replacement in the word value
  6443. # push to replace word value
  6444. ::debug("replace", "Positional done: $w\n");
  6445. for my $arg (@arg) {
  6446. my $val = $w;
  6447. my $number_of_replacements = 0;
  6448. for my $perlexpr (keys %{$self->{'replacecount'}}) {
  6449. # Replace {= perl expr =} with value for each arg
  6450. $number_of_replacements +=
  6451. $val =~ s{\257<\Q$perlexpr\E\257>}
  6452. {$arg ? $arg->replace($perlexpr,$quote_arg,$self) : ""}eg;
  6453. }
  6454. my $ww = $word;
  6455. if($quote) {
  6456. $ww = ::shell_quote_scalar($word);
  6457. $val = ::shell_quote_scalar($val);
  6458. }
  6459. if($number_of_replacements) {
  6460. CORE::push(@{$replace{$ww}}, $val);
  6461. }
  6462. }
  6463. }
  6464. if($quote) {
  6465. @target = ::shell_quote(@target);
  6466. }
  6467. # ::debug("replace", "%replace=",::my_dump(%replace),"\n");
  6468. if(%replace) {
  6469. # Substitute the replace strings with the replacement values
  6470. # Must be sorted by length if a short word is a substring of a long word
  6471. my $regexp = join('|', map { my $s = $_; $s =~ s/(\W)/\\$1/g; $s }
  6472. sort { length $b <=> length $a } keys %replace);
  6473. for(@target) {
  6474. s/($regexp)/join(" ",@{$replace{$1}})/ge;
  6475. }
  6476. }
  6477. ::debug("replace", "Return @target\n");
  6478. return wantarray ? @target : "@target";
  6479. }
  6480. package CommandLineQueue;
  6481. sub new {
  6482. my $class = shift;
  6483. my $commandref = shift;
  6484. my $read_from = shift;
  6485. my $context_replace = shift;
  6486. my $max_number_of_args = shift;
  6487. my $return_files = shift;
  6488. my @unget = ();
  6489. my ($count,%replacecount,$posrpl,$perlexpr,%len);
  6490. my @command = @$commandref;
  6491. # If the first command start with '-' it is probably an option
  6492. if($command[0] =~ /^\s*(-\S+)/) {
  6493. # Is this really a command in $PATH starting with '-'?
  6494. my $cmd = $1;
  6495. if(not ::which($cmd)) {
  6496. ::error("Command ($cmd) starts with '-'. Is this a wrong option?\n");
  6497. ::wait_and_exit(255);
  6498. }
  6499. }
  6500. # Replace replacement strings with {= perl expr =}
  6501. # Protect matching inside {= perl expr =}
  6502. # by replacing {= and =} with \257< and \257>
  6503. for(@command) {
  6504. if(/\257/) {
  6505. ::error("Command cannot contain the character \257. Use a function for that.\n");
  6506. ::wait_and_exit(255);
  6507. }
  6508. s/\Q$Global::parensleft\E(.*?)\Q$Global::parensright\E/\257<$1\257>/gx;
  6509. }
  6510. for my $rpl (keys %Global::rpl) {
  6511. # Replace the short hand string with the {= perl expr =} in $command and $opt::tagstring
  6512. # Avoid replacing inside existing {= perl expr =}
  6513. for(@command,@Global::ret_files) {
  6514. while(s/((^|\257>)[^\257]*?) # Don't replace after \257 unless \257>
  6515. \Q$rpl\E/$1\257<$Global::rpl{$rpl}\257>/xg) {
  6516. }
  6517. }
  6518. if(defined $opt::tagstring) {
  6519. for($opt::tagstring) {
  6520. while(s/((^|\257>)[^\257]*?) # Don't replace after \257 unless \257>
  6521. \Q$rpl\E/$1\257<$Global::rpl{$rpl}\257>/x) {}
  6522. }
  6523. }
  6524. # Do the same for the positional replacement strings
  6525. # A bit harder as we have to put in the position number
  6526. $posrpl = $rpl;
  6527. if($posrpl =~ s/^\{//) {
  6528. # Only do this if the shorthand start with {
  6529. for(@command,@Global::ret_files) {
  6530. s/\{(-?\d+)\Q$posrpl\E/\257<$1 $Global::rpl{$rpl}\257>/g;
  6531. }
  6532. if(defined $opt::tagstring) {
  6533. $opt::tagstring =~ s/\{(-?\d+)\Q$posrpl\E/\257<$1 $perlexpr\257>/g;
  6534. }
  6535. }
  6536. }
  6537. my $sum = 0;
  6538. while($sum == 0) {
  6539. # Count how many times each replacement string is used
  6540. my @cmd = @command;
  6541. my $contextlen = 0;
  6542. my $noncontextlen = 0;
  6543. my $contextgroups = 0;
  6544. for my $c (@cmd) {
  6545. while($c =~ s/ \257<([^\257]*?)\257> /\000/x) {
  6546. # %replacecount = { "perlexpr" => number of times seen }
  6547. # e.g { "$_++" => 2 }
  6548. $replacecount{$1} ++;
  6549. $sum++;
  6550. }
  6551. # Measure the length of the context around the {= perl expr =}
  6552. # Use that {=...=} has been replaced with \000 above
  6553. # So there is no need to deal with \257<
  6554. while($c =~ s/ (\S*\000\S*) //x) {
  6555. my $w = $1;
  6556. $w =~ tr/\000//d; # Remove all \000's
  6557. $contextlen += length($w);
  6558. $contextgroups++;
  6559. }
  6560. # All {= perl expr =} have been removed: The rest is non-context
  6561. $noncontextlen += length $c;
  6562. }
  6563. if($opt::tagstring) {
  6564. my $t = $opt::tagstring;
  6565. while($t =~ s/ \257<([^\257]*)\257> //x) {
  6566. # %replacecount = { "perlexpr" => number of times seen }
  6567. # e.g { "$_++" => 2 }
  6568. # But for tagstring we just need to mark it as seen
  6569. $replacecount{$1}||=1;
  6570. }
  6571. }
  6572. $len{'context'} = 0+$contextlen;
  6573. $len{'noncontext'} = $noncontextlen;
  6574. $len{'contextgroups'} = $contextgroups;
  6575. $len{'noncontextgroups'} = @cmd-$contextgroups;
  6576. ::debug("length", "@command Context: ", $len{'context'},
  6577. " Non: ", $len{'noncontext'}, " Ctxgrp: ", $len{'contextgroups'},
  6578. " NonCtxGrp: ", $len{'noncontextgroups'}, "\n");
  6579. if($sum == 0) {
  6580. # Default command = {}
  6581. # If not replacement string: append {}
  6582. if(not @command) {
  6583. @command = ("\257<\257>");
  6584. $Global::noquote = 1;
  6585. } elsif(($opt::pipe or $opt::pipepart)
  6586. and not $opt::fifo and not $opt::cat) {
  6587. # With --pipe / --pipe-part you can have no replacement
  6588. last;
  6589. } else {
  6590. # Append {} to the command if there are no {...}'s and no {=...=}
  6591. push @command, ("\257<\257>");
  6592. }
  6593. }
  6594. }
  6595. return bless {
  6596. 'unget' => \@unget,
  6597. 'command' => \@command,
  6598. 'replacecount' => \%replacecount,
  6599. 'arg_queue' => RecordQueue->new($read_from,$opt::colsep),
  6600. 'context_replace' => $context_replace,
  6601. 'len' => \%len,
  6602. 'max_number_of_args' => $max_number_of_args,
  6603. 'size' => undef,
  6604. 'return_files' => $return_files,
  6605. 'seq' => 1,
  6606. }, ref($class) || $class;
  6607. }
  6608. sub get {
  6609. my $self = shift;
  6610. if(@{$self->{'unget'}}) {
  6611. my $cmd_line = shift @{$self->{'unget'}};
  6612. return ($cmd_line);
  6613. } else {
  6614. my $cmd_line;
  6615. $cmd_line = CommandLine->new($self->seq(),
  6616. $self->{'command'},
  6617. $self->{'arg_queue'},
  6618. $self->{'context_replace'},
  6619. $self->{'max_number_of_args'},
  6620. $self->{'return_files'},
  6621. $self->{'replacecount'},
  6622. $self->{'len'},
  6623. );
  6624. $cmd_line->populate();
  6625. ::debug("init","cmd_line->number_of_args ",
  6626. $cmd_line->number_of_args(), "\n");
  6627. if($opt::pipe or $opt::pipepart) {
  6628. if($cmd_line->replaced() eq "") {
  6629. # Empty command - pipe requires a command
  6630. ::error("--pipe must have a command to pipe into (e.g. 'cat').\n");
  6631. ::wait_and_exit(255);
  6632. }
  6633. } else {
  6634. if($cmd_line->number_of_args() == 0) {
  6635. # We did not get more args - maybe at EOF string?
  6636. return undef;
  6637. } elsif($cmd_line->replaced() eq "") {
  6638. # Empty command - get the next instead
  6639. return $self->get();
  6640. }
  6641. }
  6642. $self->set_seq($self->seq()+1);
  6643. return $cmd_line;
  6644. }
  6645. }
  6646. sub unget {
  6647. my $self = shift;
  6648. unshift @{$self->{'unget'}}, @_;
  6649. }
  6650. sub empty {
  6651. my $self = shift;
  6652. my $empty = (not @{$self->{'unget'}}) && $self->{'arg_queue'}->empty();
  6653. ::debug("run", "CommandLineQueue->empty $empty");
  6654. return $empty;
  6655. }
  6656. sub seq {
  6657. my $self = shift;
  6658. return $self->{'seq'};
  6659. }
  6660. sub set_seq {
  6661. my $self = shift;
  6662. $self->{'seq'} = shift;
  6663. }
  6664. sub quote_args {
  6665. my $self = shift;
  6666. # If there is not command emulate |bash
  6667. return $self->{'command'};
  6668. }
  6669. sub size {
  6670. my $self = shift;
  6671. if(not $self->{'size'}) {
  6672. my @all_lines = ();
  6673. while(not $self->{'arg_queue'}->empty()) {
  6674. push @all_lines, CommandLine->new($self->{'command'},
  6675. $self->{'arg_queue'},
  6676. $self->{'context_replace'},
  6677. $self->{'max_number_of_args'});
  6678. }
  6679. $self->{'size'} = @all_lines;
  6680. $self->unget(@all_lines);
  6681. }
  6682. return $self->{'size'};
  6683. }
  6684. package Limits::Command;
  6685. # Maximal command line length (for -m and -X)
  6686. sub max_length {
  6687. # Find the max_length of a command line and cache it
  6688. # Returns:
  6689. # number of chars on the longest command line allowed
  6690. if(not $Limits::Command::line_max_len) {
  6691. # Disk cache of max command line length
  6692. my $len_cache = $ENV{'HOME'} . "/.parallel/tmp/linelen-" . ::hostname();
  6693. my $cached_limit;
  6694. if(-e $len_cache) {
  6695. open(my $fh, "<", $len_cache) || ::die_bug("Cannot read $len_cache");
  6696. $cached_limit = <$fh>;
  6697. close $fh;
  6698. } else {
  6699. $cached_limit = real_max_length();
  6700. # If $HOME is write protected: Do not fail
  6701. mkdir($ENV{'HOME'} . "/.parallel");
  6702. mkdir($ENV{'HOME'} . "/.parallel/tmp");
  6703. open(my $fh, ">", $len_cache);
  6704. print $fh $cached_limit;
  6705. close $fh;
  6706. }
  6707. $Limits::Command::line_max_len = $cached_limit;
  6708. if($opt::max_chars) {
  6709. if($opt::max_chars <= $cached_limit) {
  6710. $Limits::Command::line_max_len = $opt::max_chars;
  6711. } else {
  6712. ::warning("Value for -s option ",
  6713. "should be < $cached_limit.\n");
  6714. }
  6715. }
  6716. }
  6717. return $Limits::Command::line_max_len;
  6718. }
  6719. sub real_max_length {
  6720. # Find the max_length of a command line
  6721. # Returns:
  6722. # The maximal command line length
  6723. # Use an upper bound of 8 MB if the shell allows for for infinite long lengths
  6724. my $upper = 8_000_000;
  6725. my $len = 8;
  6726. do {
  6727. if($len > $upper) { return $len };
  6728. $len *= 16;
  6729. } while (is_acceptable_command_line_length($len));
  6730. # Then search for the actual max length between 0 and upper bound
  6731. return binary_find_max_length(int($len/16),$len);
  6732. }
  6733. sub binary_find_max_length {
  6734. # Given a lower and upper bound find the max_length of a command line
  6735. # Returns:
  6736. # number of chars on the longest command line allowed
  6737. my ($lower, $upper) = (@_);
  6738. if($lower == $upper or $lower == $upper-1) { return $lower; }
  6739. my $middle = int (($upper-$lower)/2 + $lower);
  6740. ::debug("init", "Maxlen: $lower,$upper,$middle : ");
  6741. if (is_acceptable_command_line_length($middle)) {
  6742. return binary_find_max_length($middle,$upper);
  6743. } else {
  6744. return binary_find_max_length($lower,$middle);
  6745. }
  6746. }
  6747. sub is_acceptable_command_line_length {
  6748. # Test if a command line of this length can run
  6749. # Returns:
  6750. # 0 if the command line length is too long
  6751. # 1 otherwise
  6752. my $len = shift;
  6753. local *STDERR;
  6754. open (STDERR, ">", "/dev/null");
  6755. system "true "."x"x$len;
  6756. close STDERR;
  6757. ::debug("init", "$len=$? ");
  6758. return not $?;
  6759. }
  6760. package RecordQueue;
  6761. sub new {
  6762. my $class = shift;
  6763. my $fhs = shift;
  6764. my $colsep = shift;
  6765. my @unget = ();
  6766. my $arg_sub_queue;
  6767. if($colsep) {
  6768. # Open one file with colsep
  6769. $arg_sub_queue = RecordColQueue->new($fhs);
  6770. } else {
  6771. # Open one or more files if multiple -a
  6772. $arg_sub_queue = MultifileQueue->new($fhs);
  6773. }
  6774. return bless {
  6775. 'unget' => \@unget,
  6776. 'arg_number' => 0,
  6777. 'arg_sub_queue' => $arg_sub_queue,
  6778. }, ref($class) || $class;
  6779. }
  6780. sub get {
  6781. # Returns:
  6782. # reference to array of Arg-objects
  6783. my $self = shift;
  6784. if(@{$self->{'unget'}}) {
  6785. $self->{'arg_number'}++;
  6786. return shift @{$self->{'unget'}};
  6787. }
  6788. my $ret = $self->{'arg_sub_queue'}->get();
  6789. if(defined $Global::max_number_of_args
  6790. and $Global::max_number_of_args == 0) {
  6791. ::debug("run", "Read 1 but return 0 args\n");
  6792. return [Arg->new("")];
  6793. } else {
  6794. return $ret;
  6795. }
  6796. }
  6797. sub unget {
  6798. my $self = shift;
  6799. ::debug("run", "RecordQueue-unget '@_'\n");
  6800. $self->{'arg_number'} -= @_;
  6801. unshift @{$self->{'unget'}}, @_;
  6802. }
  6803. sub empty {
  6804. my $self = shift;
  6805. my $empty = not @{$self->{'unget'}};
  6806. $empty &&= $self->{'arg_sub_queue'}->empty();
  6807. ::debug("run", "RecordQueue->empty $empty");
  6808. return $empty;
  6809. }
  6810. sub arg_number {
  6811. my $self = shift;
  6812. return $self->{'arg_number'};
  6813. }
  6814. package RecordColQueue;
  6815. sub new {
  6816. my $class = shift;
  6817. my $fhs = shift;
  6818. my @unget = ();
  6819. my $arg_sub_queue = MultifileQueue->new($fhs);
  6820. return bless {
  6821. 'unget' => \@unget,
  6822. 'arg_sub_queue' => $arg_sub_queue,
  6823. }, ref($class) || $class;
  6824. }
  6825. sub get {
  6826. # Returns:
  6827. # reference to array of Arg-objects
  6828. my $self = shift;
  6829. if(@{$self->{'unget'}}) {
  6830. return shift @{$self->{'unget'}};
  6831. }
  6832. my $unget_ref=$self->{'unget'};
  6833. if($self->{'arg_sub_queue'}->empty()) {
  6834. return undef;
  6835. }
  6836. my $in_record = $self->{'arg_sub_queue'}->get();
  6837. if(defined $in_record) {
  6838. my @out_record = ();
  6839. for my $arg (@$in_record) {
  6840. ::debug("run", "RecordColQueue::arg $arg\n");
  6841. my $line = $arg->orig();
  6842. ::debug("run", "line='$line'\n");
  6843. if($line ne "") {
  6844. for my $s (split /$opt::colsep/o, $line, -1) {
  6845. push @out_record, Arg->new($s);
  6846. }
  6847. } else {
  6848. push @out_record, Arg->new("");
  6849. }
  6850. }
  6851. return \@out_record;
  6852. } else {
  6853. return undef;
  6854. }
  6855. }
  6856. sub unget {
  6857. my $self = shift;
  6858. ::debug("run", "RecordColQueue-unget '@_'\n");
  6859. unshift @{$self->{'unget'}}, @_;
  6860. }
  6861. sub empty {
  6862. my $self = shift;
  6863. my $empty = (not @{$self->{'unget'}} and $self->{'arg_sub_queue'}->empty());
  6864. ::debug("run", "RecordColQueue->empty $empty");
  6865. return $empty;
  6866. }
  6867. package MultifileQueue;
  6868. @Global::unget_argv=();
  6869. sub new {
  6870. my $class = shift;
  6871. my $fhs = shift;
  6872. for my $fh (@$fhs) {
  6873. if(-t $fh) {
  6874. ::warning("Input is read from the terminal. ".
  6875. "Only experts do this on purpose. ".
  6876. "Press CTRL-D to exit.\n");
  6877. }
  6878. }
  6879. return bless {
  6880. 'unget' => \@Global::unget_argv,
  6881. 'fhs' => $fhs,
  6882. 'arg_matrix' => undef,
  6883. }, ref($class) || $class;
  6884. }
  6885. sub get {
  6886. my $self = shift;
  6887. if($opt::xapply) {
  6888. return $self->xapply_get();
  6889. } else {
  6890. return $self->nest_get();
  6891. }
  6892. }
  6893. sub unget {
  6894. my $self = shift;
  6895. ::debug("run", "MultifileQueue-unget '@_'\n");
  6896. unshift @{$self->{'unget'}}, @_;
  6897. }
  6898. sub empty {
  6899. my $self = shift;
  6900. my $empty = (not @Global::unget_argv
  6901. and not @{$self->{'unget'}});
  6902. for my $fh (@{$self->{'fhs'}}) {
  6903. $empty &&= eof($fh);
  6904. }
  6905. ::debug("run", "MultifileQueue->empty $empty ");
  6906. return $empty;
  6907. }
  6908. sub xapply_get {
  6909. my $self = shift;
  6910. if(@{$self->{'unget'}}) {
  6911. return shift @{$self->{'unget'}};
  6912. }
  6913. my @record = ();
  6914. my $prepend = undef;
  6915. my $empty = 1;
  6916. for my $fh (@{$self->{'fhs'}}) {
  6917. my $arg = read_arg_from_fh($fh);
  6918. if(defined $arg) {
  6919. # Record $arg for recycling at end of file
  6920. push @{$self->{'arg_matrix'}{$fh}}, $arg;
  6921. push @record, $arg;
  6922. $empty = 0;
  6923. } else {
  6924. ::debug("run", "EOA ");
  6925. # End of file: Recycle arguments
  6926. push @{$self->{'arg_matrix'}{$fh}}, shift @{$self->{'arg_matrix'}{$fh}};
  6927. # return last @{$args->{'args'}{$fh}};
  6928. push @record, @{$self->{'arg_matrix'}{$fh}}[-1];
  6929. }
  6930. }
  6931. if($empty) {
  6932. return undef;
  6933. } else {
  6934. return \@record;
  6935. }
  6936. }
  6937. sub nest_get {
  6938. my $self = shift;
  6939. if(@{$self->{'unget'}}) {
  6940. return shift @{$self->{'unget'}};
  6941. }
  6942. my @record = ();
  6943. my $prepend = undef;
  6944. my $empty = 1;
  6945. my $no_of_inputsources = $#{$self->{'fhs'}} + 1;
  6946. if(not $self->{'arg_matrix'}) {
  6947. # Initialize @arg_matrix with one arg from each file
  6948. # read one line from each file
  6949. my @first_arg_set;
  6950. my $all_empty = 1;
  6951. for (my $fhno = 0; $fhno < $no_of_inputsources ; $fhno++) {
  6952. my $arg = read_arg_from_fh($self->{'fhs'}[$fhno]);
  6953. if(defined $arg) {
  6954. $all_empty = 0;
  6955. }
  6956. $self->{'arg_matrix'}[$fhno][0] = $arg || Arg->new("");
  6957. push @first_arg_set, $self->{'arg_matrix'}[$fhno][0];
  6958. }
  6959. if($all_empty) {
  6960. # All filehandles were at eof or eof-string
  6961. return undef;
  6962. }
  6963. return [@first_arg_set];
  6964. }
  6965. # Treat the case with one input source special. For multiple
  6966. # input sources we need to remember all previously read values to
  6967. # generate all combinations. But for one input source we can
  6968. # forget the value after first use.
  6969. if($no_of_inputsources == 1) {
  6970. my $arg = read_arg_from_fh($self->{'fhs'}[0]);
  6971. if(defined($arg)) {
  6972. return [$arg];
  6973. }
  6974. return undef;
  6975. }
  6976. for (my $fhno = $no_of_inputsources - 1; $fhno >= 0; $fhno--) {
  6977. if(eof($self->{'fhs'}[$fhno])) {
  6978. next;
  6979. } else {
  6980. # read one
  6981. my $arg = read_arg_from_fh($self->{'fhs'}[$fhno]);
  6982. defined($arg) || next; # If we just read an EOF string: Treat this as EOF
  6983. my $len = $#{$self->{'arg_matrix'}[$fhno]} + 1;
  6984. $self->{'arg_matrix'}[$fhno][$len] = $arg;
  6985. # make all new combinations
  6986. my @combarg = ();
  6987. for (my $fhn = 0; $fhn < $no_of_inputsources; $fhn++) {
  6988. push @combarg, [0, $#{$self->{'arg_matrix'}[$fhn]}];
  6989. }
  6990. $combarg[$fhno] = [$len,$len]; # Find only combinations with this new entry
  6991. # map combinations
  6992. # [ 1, 3, 7 ], [ 2, 4, 1 ]
  6993. # =>
  6994. # [ m[0][1], m[1][3], m[3][7] ], [ m[0][2], m[1][4], m[2][1] ]
  6995. my @mapped;
  6996. for my $c (expand_combinations(@combarg)) {
  6997. my @a;
  6998. for my $n (0 .. $no_of_inputsources - 1 ) {
  6999. push @a, $self->{'arg_matrix'}[$n][$$c[$n]];
  7000. }
  7001. push @mapped, \@a;
  7002. }
  7003. # append the mapped to the ungotten arguments
  7004. push @{$self->{'unget'}}, @mapped;
  7005. # get the first
  7006. return shift @{$self->{'unget'}};
  7007. }
  7008. }
  7009. # all are eof or at EOF string; return from the unget queue
  7010. return shift @{$self->{'unget'}};
  7011. }
  7012. sub read_arg_from_fh {
  7013. # Read one Arg from filehandle
  7014. # Returns:
  7015. # Arg-object with one read line
  7016. # undef if end of file
  7017. my $fh = shift;
  7018. my $prepend = undef;
  7019. my $arg;
  7020. do {{
  7021. # This makes 10% faster
  7022. if(not ($arg = <$fh>)) {
  7023. if(defined $prepend) {
  7024. return Arg->new($prepend);
  7025. } else {
  7026. return undef;
  7027. }
  7028. }
  7029. # ::debug("run", "read $arg\n");
  7030. # Remove delimiter
  7031. $arg =~ s:$/$::;
  7032. if($Global::end_of_file_string and
  7033. $arg eq $Global::end_of_file_string) {
  7034. # Ignore the rest of input file
  7035. close $fh;
  7036. ::debug("run", "EOF-string ($arg) met\n");
  7037. if(defined $prepend) {
  7038. return Arg->new($prepend);
  7039. } else {
  7040. return undef;
  7041. }
  7042. }
  7043. if(defined $prepend) {
  7044. $arg = $prepend.$arg; # For line continuation
  7045. $prepend = undef; #undef;
  7046. }
  7047. if($Global::ignore_empty) {
  7048. if($arg =~ /^\s*$/) {
  7049. redo; # Try the next line
  7050. }
  7051. }
  7052. if($Global::max_lines) {
  7053. if($arg =~ /\s$/) {
  7054. # Trailing space => continued on next line
  7055. $prepend = $arg;
  7056. redo;
  7057. }
  7058. }
  7059. }} while (1 == 0); # Dummy loop {{}} for redo
  7060. if(defined $arg) {
  7061. return Arg->new($arg);
  7062. } else {
  7063. ::die_bug("multiread arg undefined");
  7064. }
  7065. }
  7066. sub expand_combinations {
  7067. # Input:
  7068. # ([xmin,xmax], [ymin,ymax], ...)
  7069. # Returns: ([x,y,...],[x,y,...])
  7070. # where xmin <= x <= xmax and ymin <= y <= ymax
  7071. my $minmax_ref = shift;
  7072. my $xmin = $$minmax_ref[0];
  7073. my $xmax = $$minmax_ref[1];
  7074. my @p;
  7075. if(@_) {
  7076. # If there are more columns: Compute those recursively
  7077. my @rest = expand_combinations(@_);
  7078. for(my $x = $xmin; $x <= $xmax; $x++) {
  7079. push @p, map { [$x, @$_] } @rest;
  7080. }
  7081. } else {
  7082. for(my $x = $xmin; $x <= $xmax; $x++) {
  7083. push @p, [$x];
  7084. }
  7085. }
  7086. return @p;
  7087. }
  7088. package Arg;
  7089. sub new {
  7090. my $class = shift;
  7091. my $orig = shift;
  7092. my @hostgroups;
  7093. if($opt::hostgroups) {
  7094. if($orig =~ s:@(.+)::) {
  7095. # We found hostgroups on the arg
  7096. @hostgroups = split(/\+/, $1);
  7097. if(not grep { defined $Global::hostgroups{$_} } @hostgroups) {
  7098. ::warning("No such hostgroup (@hostgroups)\n");
  7099. @hostgroups = (keys %Global::hostgroups);
  7100. }
  7101. } else {
  7102. @hostgroups = (keys %Global::hostgroups);
  7103. }
  7104. }
  7105. return bless {
  7106. 'orig' => $orig,
  7107. 'hostgroups' => \@hostgroups,
  7108. }, ref($class) || $class;
  7109. }
  7110. sub replace {
  7111. # Calculates the corresponding value for a given perl expression
  7112. # Returns:
  7113. # The calculated string (quoted if asked for)
  7114. my $self = shift;
  7115. my $perlexpr = shift; # E.g. $_=$_ or s/.gz//
  7116. my $quote = (shift) ? 1 : 0; # should the string be quoted?
  7117. # This is actually a CommandLine-object,
  7118. # but it looks nice to be able to say {= $job->slot() =}
  7119. my $job = shift;
  7120. $perlexpr =~ s/^-?\d+ //; # Positional replace treated as normal replace
  7121. if(not defined $self->{"rpl",0,$perlexpr}) {
  7122. local $_;
  7123. if($Global::trim eq "n") {
  7124. $_ = $self->{'orig'};
  7125. } else {
  7126. $_ = trim_of($self->{'orig'});
  7127. }
  7128. ::debug("replace", "eval ", $perlexpr, " ", $_, "\n");
  7129. if(not $Global::perleval{$perlexpr}) {
  7130. # Make an anonymous function of the $perlexpr
  7131. # And more importantly: Compile it only once
  7132. if($Global::perleval{$perlexpr} =
  7133. eval('sub { no strict; no warnings; my $job = shift; '.
  7134. $perlexpr.' }')) {
  7135. # All is good
  7136. } else {
  7137. # The eval failed. Maybe $perlexpr is invalid perl?
  7138. ::error("Cannot use $perlexpr: $@\n");
  7139. ::wait_and_exit(255);
  7140. }
  7141. }
  7142. # Execute the function
  7143. $Global::perleval{$perlexpr}->($job);
  7144. $self->{"rpl",0,$perlexpr} = $_;
  7145. }
  7146. if(not defined $self->{"rpl",$quote,$perlexpr}) {
  7147. $self->{"rpl",1,$perlexpr} =
  7148. ::shell_quote_scalar($self->{"rpl",0,$perlexpr});
  7149. }
  7150. return $self->{"rpl",$quote,$perlexpr};
  7151. }
  7152. sub orig {
  7153. my $self = shift;
  7154. return $self->{'orig'};
  7155. }
  7156. sub trim_of {
  7157. # Removes white space as specifed by --trim:
  7158. # n = nothing
  7159. # l = start
  7160. # r = end
  7161. # lr|rl = both
  7162. # Returns:
  7163. # string with white space removed as needed
  7164. my @strings = map { defined $_ ? $_ : "" } (@_);
  7165. my $arg;
  7166. if($Global::trim eq "n") {
  7167. # skip
  7168. } elsif($Global::trim eq "l") {
  7169. for my $arg (@strings) { $arg =~ s/^\s+//; }
  7170. } elsif($Global::trim eq "r") {
  7171. for my $arg (@strings) { $arg =~ s/\s+$//; }
  7172. } elsif($Global::trim eq "rl" or $Global::trim eq "lr") {
  7173. for my $arg (@strings) { $arg =~ s/^\s+//; $arg =~ s/\s+$//; }
  7174. } else {
  7175. ::error("--trim must be one of: r l rl lr.\n");
  7176. ::wait_and_exit(255);
  7177. }
  7178. return wantarray ? @strings : "@strings";
  7179. }
  7180. package TimeoutQueue;
  7181. sub new {
  7182. my $class = shift;
  7183. my $delta_time = shift;
  7184. my ($pct);
  7185. if($delta_time =~ /(\d+(\.\d+)?)%/) {
  7186. # Timeout in percent
  7187. $pct = $1/100;
  7188. $delta_time = 1_000_000;
  7189. }
  7190. return bless {
  7191. 'queue' => [],
  7192. 'delta_time' => $delta_time,
  7193. 'pct' => $pct,
  7194. 'remedian_idx' => 0,
  7195. 'remedian_arr' => [],
  7196. 'remedian' => undef,
  7197. }, ref($class) || $class;
  7198. }
  7199. sub delta_time {
  7200. my $self = shift;
  7201. return $self->{'delta_time'};
  7202. }
  7203. sub set_delta_time {
  7204. my $self = shift;
  7205. $self->{'delta_time'} = shift;
  7206. }
  7207. sub remedian {
  7208. my $self = shift;
  7209. return $self->{'remedian'};
  7210. }
  7211. sub set_remedian {
  7212. # Set median of the last 999^3 (=997002999) values using Remedian
  7213. #
  7214. # Rousseeuw, Peter J., and Gilbert W. Bassett Jr. "The remedian: A
  7215. # robust averaging method for large data sets." Journal of the
  7216. # American Statistical Association 85.409 (1990): 97-104.
  7217. my $self = shift;
  7218. my $val = shift;
  7219. my $i = $self->{'remedian_idx'}++;
  7220. my $rref = $self->{'remedian_arr'};
  7221. $rref->[0][$i%999] = $val;
  7222. $rref->[1][$i/999%999] = (sort @{$rref->[0]})[$#{$rref->[0]}/2];
  7223. $rref->[2][$i/999/999%999] = (sort @{$rref->[1]})[$#{$rref->[1]}/2];
  7224. $self->{'remedian'} = (sort @{$rref->[2]})[$#{$rref->[2]}/2];
  7225. }
  7226. sub update_delta_time {
  7227. # Update delta_time based on runtime of finished job if timeout is
  7228. # a percentage
  7229. my $self = shift;
  7230. my $runtime = shift;
  7231. if($self->{'pct'}) {
  7232. $self->set_remedian($runtime);
  7233. $self->{'delta_time'} = $self->{'pct'} * $self->remedian();
  7234. ::debug("run", "Timeout: $self->{'delta_time'}s ");
  7235. }
  7236. }
  7237. sub process_timeouts {
  7238. # Check if there was a timeout
  7239. my $self = shift;
  7240. # $self->{'queue'} is sorted by start time
  7241. while (@{$self->{'queue'}}) {
  7242. my $job = $self->{'queue'}[0];
  7243. if($job->endtime()) {
  7244. # Job already finished. No need to timeout the job
  7245. # This could be because of --keep-order
  7246. shift @{$self->{'queue'}};
  7247. } elsif($job->timedout($self->{'delta_time'})) {
  7248. # Need to shift off queue before kill
  7249. # because kill calls usleep that calls process_timeouts
  7250. shift @{$self->{'queue'}};
  7251. $job->kill();
  7252. } else {
  7253. # Because they are sorted by start time the rest are later
  7254. last;
  7255. }
  7256. }
  7257. }
  7258. sub insert {
  7259. my $self = shift;
  7260. my $in = shift;
  7261. push @{$self->{'queue'}}, $in;
  7262. }
  7263. package Semaphore;
  7264. # This package provides a counting semaphore
  7265. #
  7266. # If a process dies without releasing the semaphore the next process
  7267. # that needs that entry will clean up dead semaphores
  7268. #
  7269. # The semaphores are stored in ~/.parallel/semaphores/id-<name> Each
  7270. # file in ~/.parallel/semaphores/id-<name>/ is the process ID of the
  7271. # process holding the entry. If the process dies, the entry can be
  7272. # taken by another process.
  7273. sub new {
  7274. my $class = shift;
  7275. my $id = shift;
  7276. my $count = shift;
  7277. $id=~s/([^-_a-z0-9])/unpack("H*",$1)/ige; # Convert non-word chars to hex
  7278. $id="id-".$id; # To distinguish it from a process id
  7279. my $parallel_dir = $ENV{'HOME'}."/.parallel";
  7280. -d $parallel_dir or mkdir_or_die($parallel_dir);
  7281. my $parallel_locks = $parallel_dir."/semaphores";
  7282. -d $parallel_locks or mkdir_or_die($parallel_locks);
  7283. my $lockdir = "$parallel_locks/$id";
  7284. my $lockfile = $lockdir.".lock";
  7285. if($count < 1) { ::die_bug("semaphore-count: $count"); }
  7286. return bless {
  7287. 'lockfile' => $lockfile,
  7288. 'lockfh' => Symbol::gensym(),
  7289. 'lockdir' => $lockdir,
  7290. 'id' => $id,
  7291. 'idfile' => $lockdir."/".$id,
  7292. 'pid' => $$,
  7293. 'pidfile' => $lockdir."/".$$.'@'.::hostname(),
  7294. 'count' => $count + 1 # nlinks returns a link for the 'id-' as well
  7295. }, ref($class) || $class;
  7296. }
  7297. sub acquire {
  7298. my $self = shift;
  7299. my $sleep = 1; # 1 ms
  7300. my $start_time = time;
  7301. while(1) {
  7302. $self->atomic_link_if_count_less_than() and last;
  7303. ::debug("sem", "Remove dead locks");
  7304. my $lockdir = $self->{'lockdir'};
  7305. for my $d (glob "$lockdir/*") {
  7306. ::debug("sem", "Lock $d $lockdir\n");
  7307. $d =~ m:$lockdir/([0-9]+)\@([-\._a-z0-9]+)$:o or next;
  7308. my ($pid, $host) = ($1, $2);
  7309. if($host eq ::hostname()) {
  7310. if(not kill 0, $1) {
  7311. ::debug("sem", "Dead: $d");
  7312. unlink $d;
  7313. } else {
  7314. ::debug("sem", "Alive: $d");
  7315. }
  7316. }
  7317. }
  7318. # try again
  7319. $self->atomic_link_if_count_less_than() and last;
  7320. # Retry slower and slower up to 1 second
  7321. $sleep = ($sleep < 1000) ? ($sleep * 1.1) : ($sleep);
  7322. # Random to avoid every sleeping job waking up at the same time
  7323. ::usleep(rand()*$sleep);
  7324. if(defined($opt::timeout) and
  7325. $start_time + $opt::timeout > time) {
  7326. # Acquire the lock anyway
  7327. if(not -e $self->{'idfile'}) {
  7328. open (my $fh, ">", $self->{'idfile'}) or
  7329. ::die_bug("timeout_write_idfile: $self->{'idfile'}");
  7330. close $fh;
  7331. }
  7332. link $self->{'idfile'}, $self->{'pidfile'};
  7333. last;
  7334. }
  7335. }
  7336. ::debug("sem", "acquired $self->{'pid'}\n");
  7337. }
  7338. sub release {
  7339. my $self = shift;
  7340. unlink $self->{'pidfile'};
  7341. if($self->nlinks() == 1) {
  7342. # This is the last link, so atomic cleanup
  7343. $self->lock();
  7344. if($self->nlinks() == 1) {
  7345. unlink $self->{'idfile'};
  7346. rmdir $self->{'lockdir'};
  7347. }
  7348. $self->unlock();
  7349. }
  7350. ::debug("run", "released $self->{'pid'}\n");
  7351. }
  7352. sub _release {
  7353. my $self = shift;
  7354. unlink $self->{'pidfile'};
  7355. $self->lock();
  7356. my $nlinks = $self->nlinks();
  7357. ::debug("sem", $nlinks, "<", $self->{'count'});
  7358. if($nlinks-- > 1) {
  7359. unlink $self->{'idfile'};
  7360. open (my $fh, ">", $self->{'idfile'}) or
  7361. ::die_bug("write_idfile: $self->{'idfile'}");
  7362. print $fh "#"x$nlinks;
  7363. close $fh;
  7364. } else {
  7365. unlink $self->{'idfile'};
  7366. rmdir $self->{'lockdir'};
  7367. }
  7368. $self->unlock();
  7369. ::debug("sem", "released $self->{'pid'}\n");
  7370. }
  7371. sub atomic_link_if_count_less_than {
  7372. # Link $file1 to $file2 if nlinks to $file1 < $count
  7373. my $self = shift;
  7374. my $retval = 0;
  7375. $self->lock();
  7376. ::debug($self->nlinks(), "<", $self->{'count'});
  7377. if($self->nlinks() < $self->{'count'}) {
  7378. -d $self->{'lockdir'} or mkdir_or_die($self->{'lockdir'});
  7379. if(not -e $self->{'idfile'}) {
  7380. open (my $fh, ">", $self->{'idfile'}) or
  7381. ::die_bug("write_idfile: $self->{'idfile'}");
  7382. close $fh;
  7383. }
  7384. $retval = link $self->{'idfile'}, $self->{'pidfile'};
  7385. }
  7386. $self->unlock();
  7387. ::debug("run", "atomic $retval");
  7388. return $retval;
  7389. }
  7390. sub _atomic_link_if_count_less_than {
  7391. # Link $file1 to $file2 if nlinks to $file1 < $count
  7392. my $self = shift;
  7393. my $retval = 0;
  7394. $self->lock();
  7395. my $nlinks = $self->nlinks();
  7396. ::debug("sem", $nlinks, "<", $self->{'count'});
  7397. if($nlinks++ < $self->{'count'}) {
  7398. -d $self->{'lockdir'} or mkdir_or_die($self->{'lockdir'});
  7399. if(not -e $self->{'idfile'}) {
  7400. open (my $fh, ">", $self->{'idfile'}) or
  7401. ::die_bug("write_idfile: $self->{'idfile'}");
  7402. close $fh;
  7403. }
  7404. open (my $fh, ">", $self->{'idfile'}) or
  7405. ::die_bug("write_idfile: $self->{'idfile'}");
  7406. print $fh "#"x$nlinks;
  7407. close $fh;
  7408. $retval = link $self->{'idfile'}, $self->{'pidfile'};
  7409. }
  7410. $self->unlock();
  7411. ::debug("sem", "atomic $retval");
  7412. return $retval;
  7413. }
  7414. sub nlinks {
  7415. my $self = shift;
  7416. if(-e $self->{'idfile'}) {
  7417. ::debug("sem", "nlinks", (stat(_))[3], "size", (stat(_))[7], "\n");
  7418. return (stat(_))[3];
  7419. } else {
  7420. return 0;
  7421. }
  7422. }
  7423. sub lock {
  7424. my $self = shift;
  7425. my $sleep = 100; # 100 ms
  7426. my $total_sleep = 0;
  7427. $Global::use{"Fcntl"} ||= eval "use Fcntl qw(:DEFAULT :flock); 1;";
  7428. my $locked = 0;
  7429. while(not $locked) {
  7430. if(tell($self->{'lockfh'}) == -1) {
  7431. # File not open
  7432. open($self->{'lockfh'}, ">", $self->{'lockfile'})
  7433. or ::debug("run", "Cannot open $self->{'lockfile'}");
  7434. }
  7435. if($self->{'lockfh'}) {
  7436. # File is open
  7437. chmod 0666, $self->{'lockfile'}; # assuming you want it a+rw
  7438. if(flock($self->{'lockfh'}, LOCK_EX()|LOCK_NB())) {
  7439. # The file is locked: No need to retry
  7440. $locked = 1;
  7441. last;
  7442. } else {
  7443. if ($! =~ m/Function not implemented/) {
  7444. ::warning("flock: $!");
  7445. ::warning("Will wait for a random while\n");
  7446. ::usleep(rand(5000));
  7447. # File cannot be locked: No need to retry
  7448. $locked = 2;
  7449. last;
  7450. }
  7451. }
  7452. }
  7453. # Locking failed in first round
  7454. # Sleep and try again
  7455. $sleep = ($sleep < 1000) ? ($sleep * 1.1) : ($sleep);
  7456. # Random to avoid every sleeping job waking up at the same time
  7457. ::usleep(rand()*$sleep);
  7458. $total_sleep += $sleep;
  7459. if($opt::semaphoretimeout) {
  7460. if($total_sleep/1000 > $opt::semaphoretimeout) {
  7461. # Timeout: bail out
  7462. ::warning("Semaphore timed out. Ignoring timeout.");
  7463. $locked = 3;
  7464. last;
  7465. }
  7466. } else {
  7467. if($total_sleep/1000 > 30) {
  7468. ::warning("Semaphore stuck for 30 seconds. Consider using --semaphoretimeout.");
  7469. }
  7470. }
  7471. }
  7472. ::debug("run", "locked $self->{'lockfile'}");
  7473. }
  7474. sub unlock {
  7475. my $self = shift;
  7476. unlink $self->{'lockfile'};
  7477. close $self->{'lockfh'};
  7478. ::debug("run", "unlocked\n");
  7479. }
  7480. sub mkdir_or_die {
  7481. # If dir is not writable: die
  7482. my $dir = shift;
  7483. my @dir_parts = split(m:/:,$dir);
  7484. my ($ddir,$part);
  7485. while(defined ($part = shift @dir_parts)) {
  7486. $part eq "" and next;
  7487. $ddir .= "/".$part;
  7488. -d $ddir and next;
  7489. mkdir $ddir;
  7490. }
  7491. if(not -w $dir) {
  7492. ::error("Cannot write to $dir: $!\n");
  7493. ::wait_and_exit(255);
  7494. }
  7495. }
  7496. # Keep perl -w happy
  7497. $opt::x = $Semaphore::timeout = $Semaphore::wait =
  7498. $Job::file_descriptor_warning_printed = 0;