TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Writing Safe Shell Scripts (2019)

504 pointsby rrampageover 5 years ago

25 comments

meksterover 5 years ago
Make sure to have ShellCheck either integrated in your editor or run it before executing.<p>It really tells many of the rules you&#x27;re supposed to abide by and helps you write cleaner shell script.<p><a href="https:&#x2F;&#x2F;github.com&#x2F;koalaman&#x2F;shellcheck" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;koalaman&#x2F;shellcheck</a>
评论 #22212665 未加载
评论 #22214276 未加载
评论 #22213296 未加载
评论 #22214690 未加载
vainglorioleover 5 years ago
This is the kind of ignorance (just use python for anything it&#x27;s better + and discover subprocess(): it&#x27;s great) that burns me up. Not so many years ago actively insisting that python&#x2F;tcl&#x2F;perl were to be used instead of a 50 line shell script would have gotten you kicked out of a serious discussion. You used the power and reflection of these languages when you needed something that didn&#x27;t integrate cleanly with the rest of the unix toolkit and&#x2F;or required sophisticated data structures, controls and abstraction. These days I won&#x27;t even write python or tcl for trivial projects (including http API work just use curl&#x2F;jq and bash&#x2F;(g)awk). The number of shell one liners that just get things done in 30 seconds (rather than loading 5 libraries in python to write the same code) are innumerable. This is google thought policing the historically ignorant yet again. They are terribly opposed to the unix toolkit and C pragma that prevailed for 20 years...because they believe that they know the best way to make the world safe and productive. Self serving, smug rejections that serve the bottom line and coincidentally gain mind share for their products and approaches.
评论 #22221015 未加载
lalaland1125over 5 years ago
I really wonder whether there is really any point in writing shell scripts anymore. Practically every Unix&#x2F;Linux box in existence has at least some version of Python 2 that can be used as a complete and total replacement. I can&#x27;t think of a single situation where I would need a shell script and a Python script wouldn&#x27;t be much cleaner, simpler, and more maintainable.
评论 #22212929 未加载
评论 #22212953 未加载
评论 #22213841 未加载
评论 #22212967 未加载
评论 #22212922 未加载
评论 #22212892 未加载
评论 #22213035 未加载
评论 #22214395 未加载
评论 #22214081 未加载
评论 #22212864 未加载
评论 #22212981 未加载
评论 #22213059 未加载
评论 #22212918 未加载
评论 #22214099 未加载
评论 #22212997 未加载
评论 #22213066 未加载
评论 #22213004 未加载
评论 #22215795 未加载
评论 #22215654 未加载
评论 #22213020 未加载
评论 #22212955 未加载
评论 #22214288 未加载
评论 #22221038 未加载
smartmicover 5 years ago
Shell scripts have their well-deserved place in Unix systems. A general recommendation to use Python or other high-level scripting languages without a discussion about the reasons why and when to use shell may lead to wrong conclusions.
评论 #22212829 未加载
tjoffover 5 years ago
I&#x27;m not sure I&#x27;m comfortable with python for a typical shell script. But then again, what alternatives exist?<p>I&#x27;ve been thinking that we are kind of stuck with it. Much like javascript.<p>So, we could go the route of typescript and have a translation layer and outputting shell scripts. I actually think that could work quite well from a technical standpoint.<p>A big part of shellscripts though is having the source available. So maybe even have the translated, original code, and the generated shell output in the same file.<p>The source code on top (out of view from a shell interpreter) and the generated code below. This would allow it to be readable by anyone and executable by anyone, but modifying it would require the transpiler (which by itself would probably be pretty lightweight as well - certainly compared to python).<p>Certainly not perfect, but preferable to rediscovering the nuances and gotchas of shell-scripts every other day. Or maybe such a solution would only prolong the suffering and we should start all over.
评论 #22217099 未加载
评论 #22219668 未加载
评论 #22215863 未加载
arendtioover 5 years ago
Some time ago I started to doubt if using &#x27;set -e&#x27; is a good idea.<p>I mean, if it would work as you expect it to, it certainly is a good idea to exit a script as soon as something fails. But sadly not all implementations behave similarly [1] and if you call a function from within a condition, &#x27;set -e&#x27; gets deactivated&#x2F;doesn&#x27;t work.<p>For illustration, take a look at the following example:<p><pre><code> #!&#x2F;bin&#x2F;bash foo() { set -e false echo &quot;Sucks&quot; } printf &#x27;Normal: %s\n&#x27; &quot;$(foo)&quot; printf &#x27;Condition: %s\n&#x27; &quot;$(foo || true)&quot; </code></pre> Output:<p><pre><code> Normal: Condition: Sucks </code></pre> Probably not what you would have expected. Not using &#x27;set -e&#x27; is no good solution either, so, for the time being, I still use it, but I am still looking for a better solution.<p>[1] <a href="https:&#x2F;&#x2F;www.in-ulm.de&#x2F;~mascheck&#x2F;various&#x2F;set-e&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.in-ulm.de&#x2F;~mascheck&#x2F;various&#x2F;set-e&#x2F;</a>
评论 #22214382 未加载
评论 #22214074 未加载
评论 #22215439 未加载
评论 #22213918 未加载
chousukeover 5 years ago
Can mktemp fail? I recently wrote a script that ensures that the directory created by mktemp actually exists and starts with &#x2F;tmp so that when the script wipes out its temporary data at the end, it will not ever run something like &quot;rm -rf &#x2F;&quot;. Using fully-qualified paths for everything is also (not) fun.<p>In another script I was leery about running rm -f -- &#x2F;path&#x2F;foo* so I instead used<p><pre><code> find &#x2F;path -mindepth 1 -maxdepth 1 -name &quot;foo*&quot; -delete </code></pre> because then the glob can&#x27;t affect find&#x27;s behaviour in weird ways.<p>Most likely set -e is enough protection against mktemp failing and the rm -f glob <i>probably</i> would&#x27;ve been just fine, but shell scripting has enough footguns that sometimes I can&#x27;t help but go overboard with paranoia.
评论 #22212729 未加载
评论 #22212722 未加载
评论 #22213043 未加载
评论 #22212816 未加载
derefrover 5 years ago
I’m constantly surprised that we got a safe language that compiles to Javascript (TypeScript) but never got a safe language that compiles to shell script. Why can’t I write in (a subset of) some other scripting language $lang, but with restricted-to-pure-&#x2F;bin&#x2F;sh semantics, and then cross-compile it to actual portable shell script for distribution?<p>Hopefully not by generating a megabyte of polyfill runtime code; more just by the compiler refusing to compile code in $lang unless it has a direct equivalent in &#x2F;bin&#x2F;sh. Any $lang source file the compiler accepted, would just look like “a shell script translated into $lang” already. But the compiler would inject $lang’s safe semantics (exceptions, type-checking, etc.) during the compilation, so you’d at least get that benefit.<p>Alternately, I’d <i>also</i> be satisfied with “emscripten for shell”: a compiler that generated shell scripts containing a small WASM-like emulator and an embedded bytecode stream to feed it. As long as it was lightweight enough. (A large point of these environments’ use of &#x2F;bin&#x2F;sh is that they’re small and embedded and can’t load too much into memory at once.)<p>My only guess for why this hasn’t happened, is that the people who write things like shell scripts that execute in initramfs, or shell scripts that are intended to install stuff even on lesser-known UNIXes, are all old-hand ops people who know shell-scripting cold, and certainly <i>aren’t</i> developers with any experience in compiler theory.
评论 #22218043 未加载
评论 #22218299 未加载
tyingqover 5 years ago
Checking $PATH or explicitly calling outside resources is probably also advisible.<p>In general, this article seems very light. No mention of LD_LIBRARY_PATH, for example. I imagine there&#x27;s probably a better guide to writing secure scripts somewhere else.
评论 #22212807 未加载
loevborgover 5 years ago
For more concrete recommendations in a similar spirit, check out <a href="https:&#x2F;&#x2F;github.com&#x2F;pesterhazy&#x2F;blissful-bash" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;pesterhazy&#x2F;blissful-bash</a>
moreatiover 5 years ago
Instead of<p><pre><code> set -euf -o pipefail </code></pre> please consider<p><pre><code> set -o errexit set -o nounset set -o noglob set -o pipefail </code></pre> which is easier to lookup&#x2F;search for if the reader is less familiar with shell scripting, and makes for cleaner diffs when a flag is removed&#x2F;added.<p>Caveat: some of the longer forms might be Bashisms (e.g. not present in ksh, dash, etc.)
评论 #22213090 未加载
jakeoghover 5 years ago
I find exceptionally difficult to write anything but trivial shell scripts without bugs. This one took years, and I suspect #bash could still find a bug: <a href="https:&#x2F;&#x2F;github.com&#x2F;jakeogh&#x2F;commandlock" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;jakeogh&#x2F;commandlock</a><p>On the other hand, this is amazing: <a href="https:&#x2F;&#x2F;github.com&#x2F;speed47&#x2F;spectre-meltdown-checker" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;speed47&#x2F;spectre-meltdown-checker</a>
ilyashover 5 years ago
Hi. Author of Next Generation Shell here.<p>Here is my take on bash vs Python and friends. I am frustrated by both.<p>bash - domain specific language and huge library (CLI utilities) and lets you get the job done but not a language I would like to use (syntax, error handling, very limited structured data support).<p>Python - okayish as a language but doing domain specific things (working with files and processes) is so much more verbose than bash.<p>My solution in NGS - have a <i>high level, modern</i> language with the typical goodies like ... exceptions (wow, completely new concept!) and the language is still domain specific. Working with processes for example has it&#x27;s own syntax and is much more concise and straightforward (stole bits from bash).<p>Right now the project has the language, which is useful enough to write scripts (which we do at work). Regarding contribution to the project, my idea is that as much as possible should be in NGS language (as opposed to the lower level C). The UI will be implemented completely in NGS, allowing contributing to the project using the <i>same language</i> you are writing your scripts in.<p><a href="https:&#x2F;&#x2F;github.com&#x2F;ngs-lang&#x2F;ngs" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;ngs-lang&#x2F;ngs</a><p>As a side note, while the UI is not there yet, I do plans for it which include interaction with objects on the screen as opposed to current &quot;here is your dump of text&quot; situation... and in general be more considerate of the user.<p><a href="https:&#x2F;&#x2F;github.com&#x2F;ngs-lang&#x2F;ngs&#x2F;wiki&#x2F;UI-Design" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;ngs-lang&#x2F;ngs&#x2F;wiki&#x2F;UI-Design</a>
joana035over 5 years ago
Go write a shell script just like any other piece of code. Have fun!
cr4zyover 5 years ago
Here&#x27;s my boilerplate bash header with comments describing each option, which I find practically helpful for starting new scripts<p><a href="https:&#x2F;&#x2F;gist.github.com&#x2F;crizCraig&#x2F;f42bc250754bed764ada5f95d101dbea&#x2F;" rel="nofollow">https:&#x2F;&#x2F;gist.github.com&#x2F;crizCraig&#x2F;f42bc250754bed764ada5f95d1...</a><p>raw: <a href="https:&#x2F;&#x2F;gist.githubusercontent.com&#x2F;crizCraig&#x2F;f42bc250754bed764ada5f95d101dbea&#x2F;raw&#x2F;e3814fdb85c42afcf5766abf039f51eed67d8068&#x2F;bash_boilerplate.sh" rel="nofollow">https:&#x2F;&#x2F;gist.githubusercontent.com&#x2F;crizCraig&#x2F;f42bc250754bed7...</a>
gugagoreover 5 years ago
I personally think &quot;don&#x27;t&quot; is right. For those who are interested in trying to use Python instead, I found this to be a helpful resource: <a href="https:&#x2F;&#x2F;github.com&#x2F;ninjaaron&#x2F;replacing-bash-scripting-with-python" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;ninjaaron&#x2F;replacing-bash-scripting-with-p...</a>
评论 #22213232 未加载
评论 #22213220 未加载
arglebargle123over 5 years ago
I&#x27;ve done a bit of porting bash scripts to posix recently and I&#x27;ve found the following boilerplate pretty useful:<p><pre><code> case &quot;$(readlink &#x2F;proc&#x2F;$$&#x2F;exe)&quot; in *&#x2F;bash) set -euo pipefail ;; *) set -eu ;; esac </code></pre> That takes care of setting -eu for shells that don&#x27;t support -o pipefail and pipefail for bash.
muth02446over 5 years ago
More useful tips in the same spirit<p><a href="http:&#x2F;&#x2F;robertmuth.blogspot.com&#x2F;2012&#x2F;08&#x2F;better-bash-scripting-in-15-minutes.html" rel="nofollow">http:&#x2F;&#x2F;robertmuth.blogspot.com&#x2F;2012&#x2F;08&#x2F;better-bash-scripting...</a>
liopleurodonover 5 years ago
related: <a href="http:&#x2F;&#x2F;redsymbol.net&#x2F;articles&#x2F;unofficial-bash-strict-mode" rel="nofollow">http:&#x2F;&#x2F;redsymbol.net&#x2F;articles&#x2F;unofficial-bash-strict-mode</a>
vbernatover 5 years ago
Since it&#x27;s bash-specific, I think people should use zsh instead. No need to quote variables as by default, splitting is not done. And you get access to arrays and associative arrays.
评论 #22212964 未加载
评论 #22214146 未加载
tomohawkover 5 years ago
On set -e:<p>This is like adding a setting to your Java or Python program to immediately exit if any method call throws any kind of exception, with no possibility of catching and handling that exception.<p>This does not seem to be a smart thing to do as compared to checking return codes, etc.<p>Every script I&#x27;ve seen with set -e has been buggier than without it.<p>The main problem with scripts is that they often do not go through a normal software review and testing process.
DonHopkinsover 5 years ago
The first piece of advice, &quot;Don&#x27;t&quot;, is the best. &quot;shellcheck myscript.sh&quot; should return a fatal error if the shell script file you&#x27;re checking exists, and &quot;shellcheck -f myscript.sh&quot; should fix your shell script by removing it.
cdaringeover 5 years ago
Amen.<p>deno, node, python, julia--anything but shell scripting.
alexis_frover 5 years ago
At the beginning of each file:<p><pre><code> #!&#x2F;bin&#x2F;bash set -euf -o pipefail cd $(dirname $0) </code></pre> Then add &quot;&quot; everywhere ;) And they say, write Python instead, except I’m dubious because python programs can have a lot of dependencies which can be tricky to install.
评论 #22212941 未加载
seorphatesover 5 years ago
Not to be that guy but this is mostly garbage. I suggest simply paying attention and testing. Switches can be a useful part of the tool but they can break things. It doesn&#x27;t make things better rather it alters behaviors of the shell in sometimes unintended ways. Try some loops with some -eo. If you have a pipe that fails your script you&#x27;re just ripping the heart and potential out of your script. I think you might just be looking for one-liners. It can be good to catch your failures and try other things vs &quot;woop, damn, nope.&quot; Maybe you need things to fail first.<p>&quot;Quote liberally&quot; - also ripe. Mind your aPostrophes and Quotes because they do things.<p>I like writing for me and what I need done, not what or how others might have me write or how others might think it should be done.<p>The shell is a base orchestration and interface tool for your os. If you think it&#x27;s just that bad then just stick to your language of choice but please refrain from suggesting lazy habits make a better shell, they don&#x27;t.<p>Fly your own kite. It&#x27;s much more fun.
评论 #22214075 未加载