I wrote two little tools today,
errno – Looking up Error Numbers
The fact that this utility doesn’t really exist had always bothered me, so I wrote it myself after grepping through
/usr/include looking for
ESOMETHING constants and their numeric definitions.
It works like a little something like this:
$ errno 2 ENOENT 2 No such file or directory $ errno EAFNOSUPPORT EAGAIN EWOULDBLOCK EINVAL EAFNOSUPPORT 47 Address family not supported by protocol family EAGAIN 35 Resource temporarily unavailable EAGAIN 35 Resource temporarily unavailable EINVAL 22 Invalid argument $ errno | grep Bad EBADF 9 Bad file descriptor EFAULT 14 Bad address EPROCUNAVAIL 76 Bad procedure for program EBADEXEC 85 Bad executable (or shared library) EBADARCH 86 Bad CPU type in executable EBADMSG 94 Bad message
This can be quite handy when all you get from a program is the error message (i.e. ‘Invalid argument’) and you’re trying to track down which system call is failing. Most kernels ship with pretty good syscall man pages, and they tend to list all of the possible values of
errno that can result, and why.
ERRORS The socket() system call fails if: [EACCES] Permission to create a socket of the specified type and/or protocol is denied. [EAFNOSUPPORT] The specified address family is not supported. [EMFILE] The per-process descriptor table is full. [ENFILE] The system file table is full. [ENOBUFS] Insufficient buffer space is available. The socket cannot be created until sufficient resources are freed. [ENOMEM] Insufficient memory was available to fulfill the request. [EPROTONOSUPPORT] The protocol type or the specified protocol is not supported within this domain. [EPROTOTYPE] The socket type is not supported by the protocol. If a new protocol family is defined, the socreate process is free to return any desired error code. The socket() system call will pass this error code along (even if it is undefined).
Now, if you get
ENOMEM, and print a message via
strerror(3), you’ll get something like this in your output stream:
Cannot allocate memory
errno, you can reverse that process and get back the
ENOMEM constant, with ease:
errno | grep 'Cannot allocate memory' ENOMEM 12 Cannot allocate memory
Hey, look at that! It’s
ENOMEM. Incidentally, on my Macbook, that maps to the numeric error code 12. Neat.
errno utility also lets you “preview” the error message a given code will produce, which can be helpful in supporting lots of different platforms.
The code for
errno is over here, on Github
rlog – Ring Buffer Logging
A ring buffer, or circular buffer is a constant-space data structure that prioritizes newer things over older things.
rlog is a Ring Buffer Logging utility that brings an innovative twist to the collection, retrieval and long-term obligation of debug logging.
Ah, debugging, that glorious panacea of the operations world.
If only I had debugging mode turned on, I bet I could get to the bottom of this weird problem! But turning it on means restarting the daemon, and I may not be able to reproduce the problem once that happens!
Oh what’s a cloud engineer to do!?
One solution, popular with people who like to pay for lots and lots of storage and then never read the logs, is to just log everything, all the time. They set up centralized syslog, Hadoop, Elastic Search, Cassandra, or even -gasp- MongoDB. After a few weeks, there is so much data to look through, it’s pointless to even try!
Rather than do that, I wrote
rlog reads every line from standard input, and date stamps each. It allocates enough space to retain 2048 messages. When the 2049th message is received, the 1st messages is dropped. The 2050th messages pushes out the 2nd message, and so on.
When a client connects to
rlog (usually via
127.0.0.1:1040), they receive the most recent 2048 messages immediately (hence the date stamps), and then receive future messages as they are received by
tail -f, except (a) there is no file and (b) it takes up no disk space.
I’ll be using
rlog to provide high-resolution debugging output from live production systems. When I need the diagnostics, I hook up a
nc process to the port. When I don’t, it’s chewing a (small) constant amount of RAM. Win-win!
rlog is also over at Github
Little Tools = The Best Tools
They can be sharp. They don’t take a lot of time to build. The low time investment makes them more malleable; easier to fix; improve; expand.