Two New Commands

I enjoy learning new things. When I do, I’ll try to write them down in case others may perhaps also find them useful. If nothing else, the notes may help me when I’m wondering, “How did this get solved last time?”

My team at work is in the process of switch from Subversion to Git and GitHub. Git is new ground for many of us, as is the bash prompt (On Windows, Git includes a full-fledged bash prompt). Doing some troubleshooting today, I learned some new new things about both tools.

Pretty git logs

The first was a new Git command:
 git log --graph --oneline

This creates a wonderful ASCII-art timeline, showing all your commits and showing how files have been merged into the project.

For a project of any complexity, this simple visualization is wonderful for understanding the flow of changes and merges by multiple developers. Check out this snippet from PhantomCSS for example:

blair@Squawk MINGW64 ~/test
$ git log --graph --oneline
* 20db940 0.10.4
* a482cc3 Merge pull request #127 from raveclassic/master
|\
| * bbbaa22 fixed TypeError when calling phantomcss.compareAll() #68
* | e44196e Merge pull request #125 from shadowfiles/extension-settings
|\ \
| * | 28a397f Added option to specify the suffix names of screenshot types.
| |/
* | d8479cf Merge pull request #124 from renanborgez/patch-1
|\ \
| |/
|/|
| * 4b0913f Update README.md
|/
* 84945e5 0.10.2

 

Commit 4b0913f (near the bottom) updates the README.md and is then meged back in commit d8479cf.  Meanwhile, a separate developer is adding new functionality in commit 28a397f, merges two pull requests in commits e44196e and bbbaa22 before everything comes back together in a482cc3

It’s a bit cryptic at first, but much easier to fathom than the straight up git log.

The same format also appears, in a non-text based format, in the gitk tool.

A new (to me) bash command

The other new command was from bash. I’ve known for a while that your command line history is stored in ~/.bash_history, but I didn’t know what it was good for aside from presumably powering the up-arrow / down arrow line-at-a-time history.

Turns out that the history command also displays your command line history, and it’s waaaaay more convenient than typing
more < ~/.bash_history
As a bonus, if you have multiple terminals open, this command is guaranteed to show the history for the current window rather than the one most recently closed.

Princess Leia’s Stolen Death Star Plans

In 1967, The Beatles ‏released the album “Sgt. Pepper’s Lonley Hearts Club Band.”
In 1977, Star Wars opened.
In 2017, the band Palette-Swap Ninja, released a mash up of the two.

Some of the tracks don’t do much for me. For example, although the lyrics are moderately clever, “Luke is in the desert, whining” just hits me as a boring bit of music. (The original Lucy in the Sky with Diamonds hits me about the same way.)

On the other hand, some of the other tracks are downright brilliant. I particularly like the way they managed to work some of the original music, for example the cantina band in “Being From the Spaceport of Mos Eisley.”

And if that wasn’t enough, they also put together a YouTube playlist to go with it so you can see watch story unfold and read (and sing) along with the lyrics.

(Image credit: Palette-Swap Ninja)

Cabal and Other Irresponsible Invocations of The Muse

Writer-pal Michael Jan Friedman is in the final days of a KickStarter campaign for a new book titled Cabal and Other Irresponsible Invocations of The Muse.

From the descriptions, it sounds like a fun assortment of Science Fiction and Fantasy. There’s one story, which defies classification (Mike says it belongs in every section of the bookstore): it’s a police procedural set in an alternate universe, modern-day, Aztec empire, and features a detective named Maxtla Colhua — the very same character whom Maxtla is named for.

If any of this intrigues you, please do check out his KickStarter campaign. I’d really like to read this.

(Image via MichaelJanFriedman.Net)

Protecting Your Online Data

Advertisement for Norton VPN Dad forwarded an email he got from Symantec today. The subject line was “Breaking: New legislation affects your online privacy” and went on to suggest he could subscribe to their “Norton WiFi Privacy” product to stop his Internet Service Provider from selling his browsing data.

My take is that he should save his money. This is just Symantec doing some very opportunistic, and cynical, marketing. The place where a VPN is most valuable is when you’re using a network you don’t know whether to trust (e.g. the free WiFi at your neighborhood sub shop).

For now at least, Comcast, Verizon, AT&T and probably others are making a big deal about how they’re not collecting/selling your web browsing behavior (though they’re certainly leaving room to change that once the furor dies down — they did after all spend a huge amount of money lobbying against those rules).

Even without VPN, when you visit a web site that uses HTTPS (and more than half of the web does now), your internet provider can’t tell what you did there. They can certainly tell that you visited https://www.mybank.com, but because it’s https:// instead of http://, they can’t tell what specific pages you visited.

USA Today had a good article about some ways to protect your online privacy. Subscribing to a VPN service wasn’t one of them.

String Types

Not quite a year ago, I received a .Net Rocks! mug from Richard Campbell and Carl Franklin after a comment I’d left for a previous episode was read on the show. History repeated itself on Thursday when they used another of my comments, this time one about C++, as the lead-in for the show’s main topic.

Thursday’s show was about a scripting language, chaiscript, that allows you to write scripts in C++ and use them from other C++ projects. (C++ as a scripting language is a neat trick since it’s normally compiled ahead of time and shipped to the user as a binary executable.) It’s an interesting show and you should absolutely give it a listen. There’s also an interesting bit around the 20 mark, talking about the Commodore 64 (I had no idea those disk drives had CPUs).

The gist of my comment was that some of the features added to C++ since I’d last used it sounded rather compelling (particularly “stack semantics” which sound like there’s a sharply reduced need for new and delete, and that even pointers are largely hidden). I still have reservations though because of “scars from working with a half-dozen different, not-quite compatible string types.”

The first web application I ever worked on was a bit of a brownfield product, sharing code for the business logic with a desktop product that used the Microsoft Foundation Classes library (MFC). The resulting web application started off with char * along with the MFC CString class. (That’s two string types right there.)

Because this application ran on Active Server Pages (so-called “Classic ASP”), we soon added the BSTR and CComBSTR types in order to work with COM. And then, every so often, a new “sheriff” would attempt to unify things under a single “standard” class, which meant the introduction of TCHAR, wchar_t *, std::string and std::wstring. (Of course, as we all know, unifying under a new standard just makes things worse.)

So that’s really eight not-quite-compatible string types.

It was definitely a learning experience (if for no other reason than the anti-patterns), but I very much enjoy the fact that the C#, Java, and JavaScript languages only have one string type apiece.

Docker Tips

I’ve been working with Docker the past few months and all-in-all, I’ve been very pleased with the quality of the documentation. But, as with any other tool, there are always a few tricks to pick up, particularly when trying to script things out for an automated build or deployment. I’ve listed some of the more useful ones below and will update this post as I learn new ones.

Note: These are mainly oriented around running Docker in a Linux environment, as that’s where I’m currently using it.

How do I stop typing sudo all the time?

Docker runs as root, so when you’re working with an out-of-the-box installation, the docker command must be preceded by sudo. Since it may not be desirable for all Docker users to be able to execute commands as root, the installation creates a docker group. Members of the group may execute docker commands without elevated privileges.

To add users to the group, execute the command:
sudo usermod -aG docker <username>

How do I remove all stopped containers?

When a container is stopped, it remains loaded. You can remove it by issuing the command docker rm container_name, but that can be a hassle if you have a large number of containers loaded and they all have random names (a frequent occurrence when you’re first learning Docker).

You can remove all stopped containers by executing the command:
docker rm $(docker ps --quiet -a --filter status=exited)

(The –filter option prevents errors from attempting to remove containers which are currently running.)

You can also cause your containers to remove themselves automatically by including the –rm option on the docker run command line.

How do I know if a container is running?

To determine if a named container (e.g. “clever_leakey”) is currently running

containerID=$(docker ps --quiet --filter status=running --filter name=clever_leakey)

if $containerID is non-null, the named container is running. If it’s null, then the container is no longer running.

Do note however that there are other non-running states, e.g. paused, which will also return a null containerID for this test. As an alternative, to find only the containers which are stopped, use status=exited.

If the docker run command includes the –rm option, the container will be removed from memory.

(Image via openclipart under Creative Commans CC0 1.0 Universal)

Fixing Evernote’s “Could not add tray icon, error: An attempt was made to reference a token that does not exist.” message

I reinstalled Evernote a week or so back and every time I fired it up, a background window would also open containing the message “Could not add tray icon, error: An attempt was made to reference a token that does not exist.” Every time this happened, I’d dismiss the message and move on with what I was working on.

This routine got old pretty quickly so I did what any other geek would do and Googled for the message. Apparently the message has been around for a while, with the suggested fix being to reinstall Evernote. So I uninstalled Evernote, waited a few minutes, and then reinstalled it. Then I went back into the application and a background window opened with the same message.

This time, after closing both the pop-up and the main application window, I took a look in the system tray and discovered that Evernote’s “running in the background” icon was also missing. I also realized I’d never been prompted to run the installer as an administrator.

I run my computer differently than most people – the user account where I do my day-to-day work has reduced privileges. There’s a separate login for anything requiring elevated privileges, such as installing software. Most installers will either prompt you to either login as an administrator, or else they’ll install to an alternate location (generally somewhere in the %APPDATA% folder). I didn’t dig too deeply, but my best guess is that Evernote was doing the latter, but the system tray icon requires something to be installed with higher privileges.

In the end, I uninstalled Evernote again and this time made sure to re-install with admin privileges.

I haven’t seen the error message since.

(Public domain image, via pixabay)

Geek Humor

One of my co-workers retired back in the Spring, but still stops by to visit on occasion. He understood the importance of software source control, but had a few struggles with it. As he was leaving after his most recent visit, we had this brief exchange

  • Co-Worker: You know, I left on March 15 and haven’t had any tree conflicts since then.
  • Me: That’s great! No branches falling in the back yard?
  • Co-Worker: Well… at least, they weren’t trying to merge.

It’s difficult to get much geekier than when you’re making source control puns.

Problem: chmod is ignored in the Git Bash prompt

So here’s a strange one that had me baffled for a bit – the chmod command is pretty much a null operation from the Git Bash prompt (MingW64). This initially showed up on a script for launching a Docker container, but as nearly as I can tell, it happens for any shell script.

So, we have a simple script that prints out “Hello World!”.

blair@Squawk MINGW64 ~/test
$ cat foo
echo Hello World!

Simple enough. Now the thing is, I want to make this script executable. Now this particular Bash implementation will let me run ./foo and it’ll execute, but my real use case (running a Docker container) is going to have a somewhat longer name. Just as a matter of convenience, I’d like to to type just the first few characters, press tab, and have the filename expanded. And besides, your executable files should always be marked as executable.

blair@Squawk MINGW64 ~/test
$ ls -l
total 2
-rwxr-xr-x 1 blair 197121 28 Oct 18 00:20 bar*
-rw-r--r-- 1 blair 197121 18 Oct 18 00:10 foo

blair@Squawk MINGW64 ~/test
$

OK, this is an easy fix, I just need to run chmod and set the execute bit to on, right?

blair@Squawk MINGW64 ~/test
$ ls -l
total 2
-rwxr-xr-x 1 blair 197121 28 Oct 18 00:20 bar*
-rw-r--r-- 1 blair 197121 18 Oct 18 00:10 foo

blair@Squawk MINGW64 ~/test
$ chmod 744 foo
blair@Squawk MINGW64 ~/test
$ ls -l
total 2
-rwxr-xr-x 1 blair 197121 28 Oct 18 00:20 bar*
-rw-r--r-- 1 blair 197121 18 Oct 18 00:10 foo

The execute bit didn’t change. Maybe I need to use the u+x syntax instead?

$ chmod u+x foo
blair@Squawk MINGW64 ~/test
$ ls -l
total 2
-rwxr-xr-x 1 blair 197121 28 Oct 18 00:20 bar*
-rw-r--r-- 1 blair 197121 18 Oct 18 00:10 foo

Still no luck. So why is bar marked as executable? What’s the difference between these two scripts? The answer turns out to be one line of code:

blair@Squawk MINGW64 ~/test
$ chmod u+x foo
blair@Squawk MINGW64 ~/test
$ cat bar
#!/bin/sh
echo Hello World!

Do you see that first line, where it says “#!/bin/sh”. That’s how Bash knows what interpreter to pass the script to. It also turns out, in this particular implementation, that’s how Bash knows the file contains an executable script instead of just text.

So we modify foo, and get this result:

blair@Squawk MINGW64 ~/test$ cat foo
#!/bin/sh
echo Hello World!
blair@Squawk MINGW64 ~/test
$ ls -l
total 2
-rwxr-xr-x 1 blair 197121 28 Oct 18 00:20 bar*
-rwxr--r-- 1 blair 197121 18 Oct 18 00:10 foo*

(Image credit: Screenshot by ThatBlairGuy)