Monday, November 26, 2018

Soup: Split Pea with Turkey

Thanksgiving took place under my roof, so naturally I took custody of the turkey carcass - with an eye toward soup, of course! On the other hand, I've had a hankering for split pea soup, but preferring to avoid all the sodium that ham is full of.

Enter this recipe. I used turkey broth instead of chicken. And instead of ham, I used the turkey that boiled off the bones during the broth-making. And I left out the salt (and forgot about the pepper).

It's really good!

There's still plenty of broth left over, some of which will turn into Sherry Noodle Soup. But I also plan to make a batch (or half batch) of split pea with a cup of water swapped out for sherry. UPDATE: I swapped 1/2 cup water for sherry, which really helps when you cook without salt. It was a great addition!

Saturday, November 17, 2018

Apache Reverse Proxy for Microservice Subdomain

You've got Apache 2 running. What more does a plain-old simple HTML site need, after all?

Now you want to add a microservice, but you don't want to add more hosting. Can you add it to this existing host? Yes you can!

Here's how to add a subdomain - tictactoe.example.com - that will send requests to your microservice that's listening on port 8888.

Put the following in /etc/apache2/sites-available/tictactoe.com.conf

<VirtualHost *:80>
    ServerName tictactoe.example.com

    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html

    ProxyPass "/"  "http://example.com:8888/"
    ProxyPassReverse "/"  "http://example.com:8888/"

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>


Then add your site:

sudo a2ensite tictactoe.com

The best part is your Go code (or Rust, Ruby, Python, whatever) can just handle HTTP. You can use Let's Encrypt/certbot to add the HTTPS virtual host that will proxy secure traffic to your microservice as well.

UPDATE: Nothing like getting an invalid command error trying to do this on an Apache without proxy enabled. So...

sudo a2enmod proxy_http

Sunday, November 11, 2018

All kinds of Ubuntu troubles (fixed)

All three kinds of Ubuntu troubles (all of them fixed)

1. Can't get Ubuntu to start up without using recovery mode? Try making this change in /etc/defaults/grub

GRUB_CMDLINE_LINUX_DEFAULT="nomodeset" 

But then don't forget to

$ sudo update-grub

I've lost track of all the sites I looked at that steered me in the right direction, but I was still having trouble because I'd forgotten the update-grub step!



2a. Trouble getting VNC to install and start up? Look no further than Ubuntu's own Screen Sharing feature!

2b. Once I got that working, I discovered that I could not connect using:
  • the RealVNC viewer (error: "Unable to connect to VNC Server using your chosen security setting. Either upgrade VNC Server to a more recent version from RealVNC, or select a weaker level of encryption.")
  • MacOS Screen Sharing (error: "The software on the remote computer appears to be incompatible with this version of Screen Sharing.")
Fortunately I found a video explaining the solution. Install and launch dconf Editor. Then navigate to org > gnome > desktop > remote-access and turn off the require-encryption option. Once I did this, I was able to use all of my VNC clients!

Thursday, November 01, 2018

Git won't Pull

Problem: cannot connect to remote

$ git pull
nc: getaddrinfo: nodename nor servname provided, or not known
ssh_exchange_identification: Connection closed by remote host

fatal: Could not read from remote repository.

$ git remote -v
origin git@github.com:blah/blah (fetch)

origin git@github.com:blah/blah (push)

$ cat .git/config
...
sshCommand = ssh -o 'ProxyCommand=nc -X connect -x blah:80 %h %p'
...

Aha!

Possible solution: remove sshCommand line from .git/config unless you are ALWAYS connecting through the proxy server.

Friday, October 26, 2018

Sherry Noodle Soup (v2!)

Back in the day, you could find my recipe for Sherry Noodle Soup on dave-net.com. Well that old domain is long gone. And sadly, I don't think you can even find it on The Wayback Machine!

But I found it on a hard drive and decided to cook up a batch. But nah, that recipe needed a little tweak here and there. So without further ado, here's version two...

Sherry Noodle Soup

Ingredients:
  • A couple chicken bodies or one turkey frame, with a little meat left on (you'll want about two cups of meat off the bones later)
  • 3 quarts, water
  • 1 medium-large onion (half quartered, half chopped)
  • 2 tsp, salt (if you really must)
  • 1 cup, dry sherry
  • 1½ tsp, oregano
  • 1 tsp, thyme
  • 1/8 tsp, ground black pepper
  • 2 cups, chopped carrots
  • 2 cups, chopped celery
  • 2 cups, raw mushrooms (optional)
  • 1 lb, cooked pasta (or dry + ??? cups, water TBD)

Combine meaty bones, water, half of the onion (quartered) in a large pot. Bring to boil and then simmer for an hour or so.

Remove everything from the broth. Salvage whatever meat you can from the bones. Discard the bones and the soggy onion and the other yucky stuff. Set aside two cups of meat for later. The rest will make a nice sandwich! you can give to your dog! ONLY GIVE MEAT TO YOUR DOG IF YOU LEAVE OUT THE ONION.

Strain the broth. If you like, you can let it cool and skim the fat off the top.

Combine the broth with the meat and the rest of the raw onion (chopped) and everything else except for the pasta, which you should save for later. Bring it all to a boil and then simmer for 30 minutes.

Add the pasta (cooked or dry plus ??? cups of water) and simmer for another ten minutes or so.

Enjoy!!

Update (12/11/18): I made this with mushrooms for the first time the other day, and I really liked how it turned out!

Saturday, June 16, 2018

Fix your iTunes names (and numbers!)

I made a thing!

https://github.com/dldnh/fix-itunes-names

When Amazon announced they were retiring their Music Storage Subscriptions, I decided to download all of my music.
This was troublesome in a number of ways. The metadata was pretty well screwed up, so there would be songs without an artist name or album name. So I ended up downloading just one album at a time, so I would know which album was which. Yeah, total PITA.
But once that was done, I found I had a number of songs with names like 'dd-tt- Title of the Song' where dd is the disc number and tt is the track number. And thankfully so, since some of these tracks didn't have the disc or track number in the metadata.
So what I've done is made this little AppleScript (called Fix_iTunes_names.scpt) that will go through all of the songs and rename them from 'dd-tt- Title of the Song' to just 'Title of the Song' - but ONLY IF dd matches the disc number and tt matches the track number. So totally safe!
And then I added another Applescript (called Fix_itunes_names_and_numbers.scpt) for more adventurous folks that will also rename songs from 'dd-tt- Title of the Song' to just 'Title of the Song' and ALSO set the disc number and tarck number to dd and tt - but ONLY IF either number was blank to start with.
You don't have to buy me a beer or anything, but if you want to, feel free - and thanks! http://paypal.me/dldnh

Sunday, February 11, 2018

Use curl to test nginx rewrite rules

Be very careful using nginx rewrite. Consider this answer on SO:

The answer author wrote this correct rewrite rule:
location  /foo {
  rewrite /foo/(.*) /$1  break;
  proxy_pass         http://localhost:3200;
  proxy_redirect     off;
  proxy_set_header   Host $host;
}
Which was later edited erroneously:
location  /foo {
  rewrite /foo(.*) /$1  break;
  proxy_pass         http://localhost:3200;
  proxy_redirect     off;
  proxy_set_header   Host $host;
}
That very subtle change causes nginx to redirect, which is undesirable.

This can easily go unnoticed without curl testing:
$ curl -i http://localhost:8080/foo/bar
HTTP/1.1 301 Moved Permanently
Server: nginx/1.13.8
Date: Sun, 11 Feb 2018 14:18:12 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 40
Connection: keep-alive
Location: /bar

<a href="/bar">Moved Permanently</a>.
I've edited the answer back to the original.

Here's a great article about setting up nginx for serving Go apps.

NOTE: you'll need the GVM readme for an up-to-date command to install GVM.

Friday, December 15, 2017

ISP's and Markets

​The idea that an ISP can collect money from a content provider because a consumer requested content is like saying Safeway should be able to charge Kellog's for the Pop-Tarts I want to eat.

Just wait until Disney starts telling Time Warner to pony up for all the Toy Story they've been carrying. The real problem is that consumers have little or no choice of ISP. Each ISP has a practical monopoly in the markets where they operate.

In order for a free market to be a solution to some problem, there has to be a choice. I may choose from a variety of content providers, but I don't get to choose my cable company.

If a consumer doesn't like the way their ISP is regulating content, they should be able to choose a different ISP. But they can't. Maybe it's time we start regulating ISP's like the monopolies they really are.

Sunday, July 09, 2017

When resources unavail

Every so often my Linux system starts feeling poorly. Firefox will hang and won't let me close its window. So I ALT-TAB over to my terminal window to kill it.

$ ps -fewww | grep -v grep | grep firefox
bash: fork: retry: Resource temporarily unavailable
bash: fork: retry: Resource temporarily unavailable
bash: fork: retry: Resource temporarily unavailable
bash: fork: retry: Resource temporarily unavailable
bash: fork: Resource temporarily unavailable

When this first happened, I figured I would reboot and that, of course, would fix it. But I couldn't even run shutdown! That's when I thought of this extremely inelegant but useful solution:

$ cd /proc
$ kill *

And that freed up enough of whatever that I could get on with the reboot and then with my life.

When it happened today, I googled around and saw saw solutions suggesting...
  • su root and (WRONG: can't su)
  • ps blah blah and (WRONG: can't ps)
  • ulimit (hmmm... OK I'll try that.)
This particular solution suggests setting NPROC (max user processes) using ulimit -u like so:

$ ulimit -a
...

max user processes              (-u) 2047
...

$ ulimit -u 2100

Upping that value allowed me to kill and restart Firefox without rebooting!!

Thanks, IBM!!

Friday, March 24, 2017

Mac + Virtualbox/Linux ALT=CMD

By default it seems that when you run Linux in Virtualbox on a Mac, ALT will be mapped to the OPTION key and SUPER will be mapped to CMD.

It's much more natural to swap these, i.e. to map ALT to CMD.

And here's how you do it:

Create ~/.Xmodmap containing...

clear mod1
clear mod4

keycode 133 = Alt_L NoSymbol Alt_L
keycode 64 = Super_L NoSymbol Super_L

add mod1 = Alt_L
add mod4 = Super_L


And then

$ xmodmap ~/.Xmodmap

Enjoy!

Monday, January 23, 2017

VNC + Mac OS + Option Key = WINNING!!

I love my Macs, but sometimes through no real fault of their own, they can be a bit of a pain in the butt.

Take the Option Key. Very helpful if you're using the Finder.


Ever try using the Option Key when you're connected remotely to your Mac Desktop using VNC? It just doesn't work. VNC settings, nothing.

But I have discovered a solution. Simply turn on Sticky Keys and use the Keyboard Viewer. Now you can use your mouse to press the Option Key - not ideal, but in a pinch, it's better than nothing!

Here are the step-by-step instructions for setting this up:

1. Open up the Preferences


2. Choose Accessibility


3. Turn on Sticky Keys



4. Go back to Preferences and choose Keyboard


5. Turn on "Shoe keyboard and emoji viewers in menu bar"



6. Open up the Keyboard Viewer


7. Now whenever you need to hold down the Option Key, tap it in the Keyboard Viewer


8. If you didn't have Sticky Keys turned on, you'd have to keep it held down in the viewer, but you can just tap it the once. Tapping it again puts it into some other state. Tapping it a third time turns it off. So whenever I want Option, I double click it in the viewer. Then I do whatever it was that needed the Option Key in the first place. And then I tap it again to turn it off.

I hope you find this helpful!

Saturday, December 24, 2016

#selector vs Selector

TLDR: In Swift 3, use #selector instead of Selector (see here).

The warning (No method declared with Objective-C selector 'swipedLeft:') should be your first clue that there's a problem...



If you use this code in Swift 3, the left-swipe will result in an error like this:

2016-12-24 08:15:12.645 SpriteSimpleGame[65853:2987246] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SpriteSimpleGame.GameScene swipedLeft:]: unrecognized selector sent to instance 0x7fb99e4101f0'

Worst of all, examples like this are all over the place because leaving out the colon results in a similar error.

Thanks to this answer I learned that what you want instead is this:

let swipeLeft = UISwipeGestureRecognizer(
    target: self,
    action: #selector(swipedLeft(sender:))
)

Thanks, internets!!

Friday, September 09, 2016

VNC black screen of sadness

Did you connect to your VNC server only to be greeted by a black screen of sadness? 

It happened to me not long ago and I don't know what made me try this, but here's what fixed it:

$ vncpasswd

As always, you're welcome.

Monday, June 20, 2016

Old code, new Xcode

When you download some old code from the Interwebs with such like:

[self.window addSubview:self.viewController.view];

and it runs just fine... and later you update Xcode and start getting runtime errors:

Applications are expected to have a root view controller at the end of application launch

Fortunately the fix is easy:

[self.window setRootViewController:self.viewController];

Thanks, Interwebs!!

Saturday, April 23, 2016

LED Dice!

They cost me all of my diamonds, but I think it was worth it!


Thursday, April 07, 2016

Major accomplishment

I did it!! I beat the Cheshire Cat in Yahtzee Buddies!! 


The dice are cool and all, but pretty hard to read...


I'll stick to my favorite bronze dice.

Sunday, January 10, 2016

Beach Ball!!!

I finally got my beach ball dice! Yes, I had to beat 25 different opponents in 24 hours, but it was totally worth it, right? Right? 



But here's the thing. There's a bug - at least on iOS - where the progress of your wins against different opponents isn't getting updated. So if you want to earn the beach ball dice, KEEP A LIST OF THE PLAYERS YOU BEAT (and when) and then paste that information into a help request so customer service can give you credit for your achievement, as they did do for me. Thanks, Yahtzee! 

Now here's my whole lineup of dice. I do expect this will be my final update, since the remaining locked dice involve tournaments and dice masters that are impossible to beat without spending moneys on bonus rolls. C'est la vie! 


Saturday, January 02, 2016

Yahtzee!!

My dice. Don't judge me. :-)

Friday, January 01, 2016

Swift selector argument - yes you can!

Selectors are an Objective C thing, but sometimes you have to use them in Swift.

For example, if you are calling performSelectorOnMainThread to work around the problem between GCD and UIWebView that causes hangs in stringByEvaluatingJavaScriptFromString (see here) you don't have a choice.

But how to pass an argument? I defined my selector function to take AnyObject? just as I assumed I should since withObject:AnyObject?

So tl;dr - here's what I was doing wrong. The colon at the end of the selector DOES MATTER. Well duh, of course it does, because it indicates there's an argument. Here's an example of everything working correctly...

  private func caller() {
    let arg = 42
    performSelectorOnMainThread("myfunc:", withObject: arg, waitUntilDone: false)
  }

  func myfunc(arg: AnyObject?) {
    guard let n = arg as? Int else {
      print("how did we get in this cornfield?")
      return
    }
    print("and here we are with our arg n: \(n)")
  }

...and the proof of the pudding - my, how tasty!

and here we are with our arg n: 42

I hope this saves somebody else a few hours of struggle!

Thursday, December 10, 2015

What To Wear

Because I never ever remember...
°F Just Right Too Much Not Enough
56
  • warm wicking T
  • tech long sleeve T
  • shorts
  • didn't need the hat or gloves or extra LST n/a