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!
My thoughts on food, technology, politics, running and... nope, those are the only thoughts I've got!
Monday, November 26, 2018
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
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)
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.")
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.
$ 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.
origin git@github.com:blah/blah (fetch)
origin git@github.com:blah/blah (push)
...
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...
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!
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
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:
This can easily go unnoticed without curl testing:
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.
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.
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.
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:
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...
Upping that value allowed me to kill and restart Firefox without rebooting!!
Thanks, IBM!!
|
$ 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.)
|
$ 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!
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!
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:
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:
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!!
[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
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
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
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 |
| didn't need the hat or gloves or extra LST | n/a |
Subscribe to:
Posts (Atom)













