[{"data":1,"prerenderedAt":642},["ShallowReactive",2],{"mdc-h1me1i-key":3,"mdc--c27h5w-key":16,"mdc--h4tlbs-key":55,"mdc--7awprh-key":147,"mdc--qizmg4-key":231,"mdc-33qo73-key":240,"mdc-xrbeun-key":252,"mdc--jdks55-key":267,"mdc-8r25nl-key":374,"mdc-pj2qnp-key":522,"mdc--z38i3n-key":606,"mdc-ind8e5-key":619},{"data":4,"body":5},{},{"type":6,"children":7},"root",[8],{"type":9,"tag":10,"props":11,"children":12},"element","p",{},[13],{"type":14,"value":15},"text","Almost everything on a Linux system is configured with a text file and diagnosed with a text file. Reading them quickly is a genuine skill, and it starts with knowing which of four tools to reach for.",{"data":17,"body":18},{},{"type":6,"children":19},[20,27,43],{"type":9,"tag":21,"props":22,"children":24},"h2",{"id":23},"pick-the-right-reader",[25],{"type":14,"value":26},"Pick the right reader",{"type":9,"tag":10,"props":28,"children":29},{},[30,41],{"type":9,"tag":31,"props":32,"children":33},"strong",{},[34],{"type":9,"tag":35,"props":36,"children":38},"code",{"className":37},[],[39],{"type":14,"value":40},"cat",{"type":14,"value":42}," dumps a whole file to the screen. Perfect for short files, terrible for long ones — a 5,000-line log will scroll past faster than you can read and leave you at the bottom.",{"type":9,"tag":44,"props":45,"children":49},"pre",{"className":46,"code":48,"language":14},[47],"language-text","cat /etc/hostname\n",[50],{"type":9,"tag":35,"props":51,"children":53},{"__ignoreMap":52},"",[54],{"type":14,"value":48},{"data":56,"body":57},{},{"type":6,"children":58},[59,73,82],{"type":9,"tag":10,"props":60,"children":61},{},[62,71],{"type":9,"tag":31,"props":63,"children":64},{},[65],{"type":9,"tag":35,"props":66,"children":68},{"className":67},[],[69],{"type":14,"value":70},"less",{"type":14,"value":72}," opens a file in a pager you can scroll and search. This is the right default for anything you can't see in one screen.",{"type":9,"tag":44,"props":74,"children":77},{"className":75,"code":76,"language":14},[47],"less /var/log/syslog\n",[78],{"type":9,"tag":35,"props":79,"children":80},{"__ignoreMap":52},[81],{"type":14,"value":76},{"type":9,"tag":10,"props":83,"children":84},{},[85,87,92,94,100,102,108,110,116,118,124,126,132,134,145],{"type":14,"value":86},"Inside ",{"type":9,"tag":35,"props":88,"children":90},{"className":89},[],[91],{"type":14,"value":70},{"type":14,"value":93},": arrow keys or ",{"type":9,"tag":95,"props":96,"children":97},"kbd",{},[98],{"type":14,"value":99},"Space",{"type":14,"value":101}," to scroll, ",{"type":9,"tag":35,"props":103,"children":105},{"className":104},[],[106],{"type":14,"value":107},"/word",{"type":14,"value":109}," to search forwards, ",{"type":9,"tag":35,"props":111,"children":113},{"className":112},[],[114],{"type":14,"value":115},"n",{"type":14,"value":117}," for the next match, ",{"type":9,"tag":35,"props":119,"children":121},{"className":120},[],[122],{"type":14,"value":123},"G",{"type":14,"value":125}," to jump to the end, ",{"type":9,"tag":35,"props":127,"children":129},{"className":128},[],[130],{"type":14,"value":131},"g",{"type":14,"value":133}," for the start, and ",{"type":9,"tag":31,"props":135,"children":136},{},[137,143],{"type":9,"tag":35,"props":138,"children":140},{"className":139},[],[141],{"type":14,"value":142},"q",{"type":14,"value":144}," to quit",{"type":14,"value":146},". That last one matters — being stuck in a pager with no idea how to leave is a rite of passage nobody enjoys.",{"data":148,"body":149},{},{"type":6,"children":150},[151,176,185,203,212],{"type":9,"tag":10,"props":152,"children":153},{},[154,163,165,174],{"type":9,"tag":31,"props":155,"children":156},{},[157],{"type":9,"tag":35,"props":158,"children":160},{"className":159},[],[161],{"type":14,"value":162},"head",{"type":14,"value":164}," and ",{"type":9,"tag":31,"props":166,"children":167},{},[168],{"type":9,"tag":35,"props":169,"children":171},{"className":170},[],[172],{"type":14,"value":173},"tail",{"type":14,"value":175}," show you the first or last ten lines:",{"type":9,"tag":44,"props":177,"children":180},{"className":178,"code":179,"language":14},[47],"head -n 20 access.log     # first 20 lines\ntail -n 50 access.log     # last 50 lines\n",[181],{"type":9,"tag":35,"props":182,"children":183},{"__ignoreMap":52},[184],{"type":14,"value":179},{"type":9,"tag":10,"props":186,"children":187},{},[188,194,196,201],{"type":9,"tag":35,"props":189,"children":191},{"className":190},[],[192],{"type":14,"value":193},"tail -f",{"type":14,"value":195}," is the one you'll use most in real work. It shows the end of a file and then ",{"type":9,"tag":31,"props":197,"children":198},{},[199],{"type":14,"value":200},"keeps watching",{"type":14,"value":202},", printing new lines as they're written:",{"type":9,"tag":44,"props":204,"children":207},{"className":205,"code":206,"language":14},[47],"tail -f /var/log/nginx/error.log\n",[208],{"type":9,"tag":35,"props":209,"children":210},{"__ignoreMap":52},[211],{"type":14,"value":206},{"type":9,"tag":10,"props":213,"children":214},{},[215,217,222,224,229],{"type":14,"value":216},"Leave that running in one window, reproduce your bug in another, and watch the error appear in real time. ",{"type":9,"tag":95,"props":218,"children":219},{},[220],{"type":14,"value":221},"Ctrl",{"type":14,"value":223},"+",{"type":9,"tag":95,"props":225,"children":226},{},[227],{"type":14,"value":228},"C",{"type":14,"value":230}," stops it.",{"data":232,"body":233},{},{"type":6,"children":234},[235],{"type":9,"tag":236,"props":237,"children":239},"terminal-teaser",{":lines":238},"[{\"cmd\":\"head -n 3 /etc/passwd\",\"out\":\"root:x:0:0:root:/root:/bin/bash\\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\"},{\"cmd\":\"tail -f /var/log/app.log\",\"out\":\"[09:14:22] server started\\n[09:14:31] GET /health 200\\n^C\"}]",[],{"data":241,"body":242},{},{"type":6,"children":243},[244],{"type":9,"tag":245,"props":246,"children":251},"quiz",{":answer":247,":options":248,"explanation":249,"question":250},"0","[\"tail -f logfile\",\"cat logfile\",\"head -f logfile\",\"less logfile\"]","`-f` means follow. `cat` prints once and exits, `less` shows a snapshot you'd have to keep refreshing, and `head -f` isn't a thing.","You need to watch a log file as new entries arrive while you reproduce a bug. Which command?",[],{"data":253,"body":254},{},{"type":6,"children":255},[256,262],{"type":9,"tag":21,"props":257,"children":259},{"id":258},"editing-without-leaving-the-terminal",[260],{"type":14,"value":261},"Editing without leaving the terminal",{"type":9,"tag":10,"props":263,"children":264},{},[265],{"type":14,"value":266},"Sooner or later you'll need to change a config file on a machine that has no GUI. You have two realistic options.",{"data":268,"body":269},{},{"type":6,"children":270},[271,278,287,312,369],{"type":9,"tag":272,"props":273,"children":275},"h3",{"id":274},"nano-the-one-to-learn-first",[276],{"type":14,"value":277},"nano — the one to learn first",{"type":9,"tag":44,"props":279,"children":282},{"className":280,"code":281,"language":14},[47],"nano config.txt\n",[283],{"type":9,"tag":35,"props":284,"children":285},{"__ignoreMap":52},[286],{"type":14,"value":281},{"type":9,"tag":10,"props":288,"children":289},{},[290,296,298,304,306,310],{"type":9,"tag":35,"props":291,"children":293},{"className":292},[],[294],{"type":14,"value":295},"nano",{"type":14,"value":297}," behaves the way you expect a text editor to behave. Type to insert, arrow keys to move. The commands are listed along the bottom of the screen, where ",{"type":9,"tag":35,"props":299,"children":301},{"className":300},[],[302],{"type":14,"value":303},"^",{"type":14,"value":305}," means ",{"type":9,"tag":95,"props":307,"children":308},{},[309],{"type":14,"value":221},{"type":14,"value":311},":",{"type":9,"tag":313,"props":314,"children":315},"ul",{},[316,339,354],{"type":9,"tag":317,"props":318,"children":319},"li",{},[320,324,325,330,332,337],{"type":9,"tag":95,"props":321,"children":322},{},[323],{"type":14,"value":221},{"type":14,"value":223},{"type":9,"tag":95,"props":326,"children":327},{},[328],{"type":14,"value":329},"O",{"type":14,"value":331}," — write out (save), then ",{"type":9,"tag":95,"props":333,"children":334},{},[335],{"type":14,"value":336},"Enter",{"type":14,"value":338}," to confirm the filename",{"type":9,"tag":317,"props":340,"children":341},{},[342,346,347,352],{"type":9,"tag":95,"props":343,"children":344},{},[345],{"type":14,"value":221},{"type":14,"value":223},{"type":9,"tag":95,"props":348,"children":349},{},[350],{"type":14,"value":351},"X",{"type":14,"value":353}," — exit",{"type":9,"tag":317,"props":355,"children":356},{},[357,361,362,367],{"type":9,"tag":95,"props":358,"children":359},{},[360],{"type":14,"value":221},{"type":14,"value":223},{"type":9,"tag":95,"props":363,"children":364},{},[365],{"type":14,"value":366},"K",{"type":14,"value":368}," — cut the current line",{"type":9,"tag":10,"props":370,"children":371},{},[372],{"type":14,"value":373},"If nano is available, use it. There is no prize for suffering.",{"data":375,"body":376},{},{"type":6,"children":377},[378,384,395,415,420,496],{"type":9,"tag":272,"props":379,"children":381},{"id":380},"vim-the-one-youll-eventually-meet-anyway",[382],{"type":14,"value":383},"vim — the one you'll eventually meet anyway",{"type":9,"tag":10,"props":385,"children":386},{},[387,393],{"type":9,"tag":35,"props":388,"children":390},{"className":389},[],[391],{"type":14,"value":392},"vim",{"type":14,"value":394}," is on essentially every Unix machine ever built, including minimal containers and rescue images where nano isn't installed. You don't need to learn vim properly today. You need to not be trapped by it.",{"type":9,"tag":10,"props":396,"children":397},{},[398,400,405,407,413],{"type":14,"value":399},"The one idea that makes vim make sense: it has ",{"type":9,"tag":31,"props":401,"children":402},{},[403],{"type":14,"value":404},"modes",{"type":14,"value":406},". When it opens you are in ",{"type":9,"tag":408,"props":409,"children":410},"em",{},[411],{"type":14,"value":412},"normal",{"type":14,"value":414}," mode, where keys are commands, not text. This is why typing \"hello\" into a fresh vim does something alarming instead of writing \"hello\".",{"type":9,"tag":10,"props":416,"children":417},{},[418],{"type":14,"value":419},"The survival sequence:",{"type":9,"tag":421,"props":422,"children":423},"ol",{},[424,443,460,478],{"type":9,"tag":317,"props":425,"children":426},{},[427,429,434,436,441],{"type":14,"value":428},"Press ",{"type":9,"tag":95,"props":430,"children":431},{},[432],{"type":14,"value":433},"i",{"type":14,"value":435}," to enter ",{"type":9,"tag":31,"props":437,"children":438},{},[439],{"type":14,"value":440},"insert",{"type":14,"value":442}," mode. Now typing works normally.",{"type":9,"tag":317,"props":444,"children":445},{},[446,447,452,454,458],{"type":14,"value":428},{"type":9,"tag":95,"props":448,"children":449},{},[450],{"type":14,"value":451},"Esc",{"type":14,"value":453}," to return to ",{"type":9,"tag":31,"props":455,"children":456},{},[457],{"type":14,"value":412},{"type":14,"value":459}," mode.",{"type":9,"tag":317,"props":461,"children":462},{},[463,465,471,472,476],{"type":14,"value":464},"Type ",{"type":9,"tag":35,"props":466,"children":468},{"className":467},[],[469],{"type":14,"value":470},":wq",{"type":14,"value":164},{"type":9,"tag":95,"props":473,"children":474},{},[475],{"type":14,"value":336},{"type":14,"value":477}," to write and quit.",{"type":9,"tag":317,"props":479,"children":480},{},[481,483,489,490,494],{"type":14,"value":482},"Or type ",{"type":9,"tag":35,"props":484,"children":486},{"className":485},[],[487],{"type":14,"value":488},":q!",{"type":14,"value":164},{"type":9,"tag":95,"props":491,"children":492},{},[493],{"type":14,"value":336},{"type":14,"value":495}," to quit and throw away every change.",{"type":9,"tag":10,"props":497,"children":498},{},[499,501,506,508,513,515,520],{"type":14,"value":500},"That's it. ",{"type":9,"tag":35,"props":502,"children":504},{"className":503},[],[505],{"type":14,"value":451},{"type":14,"value":507},", then ",{"type":9,"tag":35,"props":509,"children":511},{"className":510},[],[512],{"type":14,"value":470},{"type":14,"value":514}," to save or ",{"type":9,"tag":35,"props":516,"children":518},{"className":517},[],[519],{"type":14,"value":488},{"type":14,"value":521}," to bail. Those four keystrokes get you out of any vim session you didn't mean to start.",{"data":523,"body":524},{},{"type":6,"children":525},[526],{"type":9,"tag":527,"props":528,"children":530},"deep-dive",{"title":529},"Why does `:q!` need the exclamation mark?",[531,536,588],{"type":9,"tag":10,"props":532,"children":533},{},[534],{"type":14,"value":535},"Because vim refuses to discard unsaved work quietly.",{"type":9,"tag":10,"props":537,"children":538},{},[539,541,547,549,555,557,562,564,570,572,578,580,586],{"type":14,"value":540},"Plain ",{"type":9,"tag":35,"props":542,"children":544},{"className":543},[],[545],{"type":14,"value":546},":q",{"type":14,"value":548}," means \"quit\". If the file has unsaved changes, vim declines and warns you. The ",{"type":9,"tag":35,"props":550,"children":552},{"className":551},[],[553],{"type":14,"value":554},"!",{"type":14,"value":556}," means \"I know, do it anyway\" — it's the same ",{"type":9,"tag":408,"props":558,"children":559},{},[560],{"type":14,"value":561},"force",{"type":14,"value":563}," idea as ",{"type":9,"tag":35,"props":565,"children":567},{"className":566},[],[568],{"type":14,"value":569},"-f",{"type":14,"value":571}," in ",{"type":9,"tag":35,"props":573,"children":575},{"className":574},[],[576],{"type":14,"value":577},"rm -rf",{"type":14,"value":579}," or ",{"type":9,"tag":35,"props":581,"children":583},{"className":582},[],[584],{"type":14,"value":585},"cp -f",{"type":14,"value":587},".",{"type":9,"tag":10,"props":589,"children":590},{},[591,593,598,599,604],{"type":14,"value":592},"The pattern shows up all over Unix: the safe version is the default, and you add something explicit to override the safety. Once you notice it, ",{"type":9,"tag":35,"props":594,"children":596},{"className":595},[],[597],{"type":14,"value":554},{"type":14,"value":164},{"type":9,"tag":35,"props":600,"children":602},{"className":601},[],[603],{"type":14,"value":569},{"type":14,"value":605}," stop looking arbitrary.",{"data":607,"body":608},{},{"type":6,"children":609},[610],{"type":9,"tag":611,"props":612,"children":618},"fill-blank",{":answer":613,"explanation":614,"hint":615,"placeholder":616,"prompt":617},"[\"tail -n 100 access.log\",\"tail -100 access.log\",\"tail --lines=100 access.log\"]","`tail -n 100` is the portable spelling; the shorter `tail -100` works on most systems too.","The command is `tail`, and the option asks for a number of lines.","tail ...","Show the last 100 lines of a file called `access.log`.",[],{"data":620,"body":621},{},{"type":6,"children":622},[623,629],{"type":9,"tag":245,"props":624,"children":628},{":answer":247,":options":625,"explanation":626,"question":627},"[\"Press Esc, then type :q! and Enter\",\"Press Ctrl+C\",\"Press Ctrl+X\",\"Type quit and press Enter\"]","Esc gets you out of insert mode into normal mode, where `:` starts a command. `q!` quits and discards changes. Ctrl+C won't do it, and Ctrl+X is nano's key.","You've opened vim by accident and typed some junk. How do you leave without saving?",[],{"type":9,"tag":10,"props":630,"children":631},{},[632,634,640],{"type":14,"value":633},"Next: permissions — the reason things say \"Permission denied\", and what ",{"type":9,"tag":35,"props":635,"children":637},{"className":636},[],[638],{"type":14,"value":639},"rwx",{"type":14,"value":641}," actually means.",1787908866327]