I've been a long time bash user because on the surface scripts are simple and easy to put together, and with Nim I usually found myself overthinking things and doing too much, just because I could. Then I realized it was silly to use a programming language with many downsides and limitatations when I realized I could just use Nim with the mindset of writing a script (that I had stubbornly refused to use in any other language than bash) to get the same kind of development speed with none of the hairy pitfalls that slow you right back down.
So recently I found myself in need of a quick health check for a few small web sites that I decided needed more monitoring without rolling out something big and complicated- and I reached for bash. It started out with something like this
[ "$(curl -Is example.com | head -1)" == "HTTP/1.1 200 OK" ] || >&2 echo example.com not available
when it occurred to me that really wasn't very readable and after a little debugging trouble I decided it wasn't worth it and I looked up the equivalent in Nim. It turned out to be:
import httpclient
if newHttpClient().get("http://example.com").status != "200 OK":
stderr.write("example.com down\n"
It's not a one liner but darn it's a lot easier to use. Then I expanded it to cover a few more use cases, which was really straight forward to do
monitor.nim
let client = newHttpClient(timeout=5000)
var errors = 0
for url in [
"http://example.com",
"https://my.example.net",
"https://example.org/my",
]:
var r:Response
try:
r = client.get(url)
except:
stderr.write url & " " & getCurrentExceptionMsg() & "\n"
continue
if r.status != "200 OK":
stderr.write url & " " & r.status & "\n"
errors += 1
quit errors
monitor.nims
--define:ssl
The file lives on the server, where I would have placed the bash script, and gets compiled like so after a change:
nim c monitor.nim
I know I could use nimscript but I prefer to just make a program and have all of nim available. The compilation step is of course another step where something could go wrong, and it could be automated, but for now I'm just careful to compile it and it works fine.
So now together with the really great cronic tool and an every-minute cron job, I have a really nice monitoring program that was a lot easier and faster to write, easier to fix, more pleasant to read, and much more predictable in its behavior than the bash script that I would have used to use.
As mentioned, main takeaway is that Nim is perfectly fine to use for this sort of plumbing programming as long as you don't feel you need to structure it like a huge application just because it gets compiled. You can just write it like you would write a bash script and you will be faster (and you get cross-platform for free). But it did take some resisting my application programmer cap who needed to be repeatedly told that it's okay to use the same tool in different contexts. I suspect overcoming this kind of psychological resistance to using a language as versatile as nim would make a cool post on its own.
Yes, I agree. Just embracing Nim for this is rather freeing! Just means my bash skills get more and more rusty though...
In case you do need to call actual shell commands sometimes, there's a couple of libraries that can help (if you don't want to use startProcess and friends of the stdlib directly).
@haxscramper wrote hshell:
https://github.com/haxscramper/hmisc#hmiscotherhshell-documentation
and I wrote the shell macro:
https://github.com/Vindaar/shell
Both try to be slightly different things, but just thought I'd mention them.
You can also just use:
#!/usr/bin/nim r
(or whatever other path to nim), though it may produce unwanted or use an unoptimized compile output depending upon your config.