Over on my project blog, I’ve written a piece on making mechanics for character classes which don’t require so many arbitrary numbers.
I dislike aubergine, but HelloFresh insist on me continuing to try it. This recipe was alright, I guess. Maybe I’ll swap out the aubergine for beans of some kind next time though!
|Onion, 1||Flat Leaf Parsley, 1/2 bunch*|
|Garlic Clove, 2||Sun-dried Tomato, 30g|
|Aubergine, 1||Chilli Flakes, a pinch*|
|Wholewheat Tagliatelle, 180g||Chopped tomatoes, 1 tin*|
|Hard Italian Cheese, as much as you like|
* Sorry these amounts are so unhelpful.
This is a pretty healthy meal, filling 4 of your 5 a day! (Which I’m sure the NHS told me was supposed to be 11 a day, at some point. You cannot win.)
FYI, so you only have to wash up some things: you’re gonna need one large pan for boiling the tagliatelle, a large frying pan which is big enough to hold all your tomatoes, onion and a baking tray. Also, a couple plates, knifes and forks. You can stop washing up now – just leave those cups for later?
- Fill the pan with water, and start it off boiling. Once it’s boiling, throw in the tagliatelle. Cook until it’s sort-of-soft-but-still-firm-kinda. Then take it off the heat.
- Cut up the aubergine. Get rid of the middle spongy bit – we won’t be using it.
- Throw this onto the baking tray with some oil, and put it in the grill. Cook until it’s a little crispy on the outsides.
- Meanwhile, chop the onion, garlic and sun-dried tomatoes. It’s okay to get these all mixed up if you run out of room. They’ll be fried together.
Here, I’ve not chopped the tomato nearly enough. Keep chopping, otherwise you’ll get surprising chewy bits in your food.
- Chop the parsley too, but keep that separate.
- Throw the onion, garlic, sun-dried tomatoes, and chili flakes into the frying pan, with a little oil. Mix these up good and proper. I did not mix well enough, and the chili flakes got all clumped in together.
- After a few minutes of these cooking, throw in the tinned tomatoes and some black pepper. Let this steam off for a few minutes, til it’s a little thicker.
- Throw in the aubergine, if it’s cooked.
- Throw in the pasta!
- Mix it all up.
- Serve with cheese and parsley on top.
This is podcast I don’t listen to enough. The PHP Roundtable episode on PHP-FIG (with so many of the team) is a really interesting one. They cover the dark times of the FIG as well as the cool times.
This has been a very sysadmin-y week for me, and I’ve mixed feelings about that. For now though, I’d like to tell the story of how I debugged why I couldn’t access my MySQL server.
My standard MO would be to have MySQL and the app running on the same machine. This time though, since I’ve built my app using Docker (which I’m deploying with Docker Cloud) I can’t have the MySQL server on the same box.
I do have a box already with MySQL running, however that box is smartly locked down with all sorts of iptables voodoo. Very few things are allowed to talk out from the server, and even fewer are allowed to talk to the server. Here are the steps I took while learning how to open that box up.
First, on the MySQL box figure out what port it’s running on. The default is 3306, but you can confirm that like so:
sudo netstat --tcp --listening --program --numeric-ports | grep 'mysql'
The number in the forth column, which looks a bunch like an IP address with a port, is the port you’re looking for.
Now we know that, we can check if our app server has access to the database server.
telnet yourhost.com 3306
Hopefully, you won’t get anything back but a quick message about it “Trying” to connect, and eventually “Network is unreachable”. If this command does actually connect you to your MySQL server then you should focus on locking that down as soon as you can.
Assuming that you’ve already got your server locked down via iptables though, you’ll want to open it up so that you app server (and only your app server’s IP) can get access to this port. I don’t know enough about system administration to get dirty with real iptables conf files though, so I much prefer to install webmin which will give you a lovely interface for it.
You want to be setting up rules which look like this:
- Source address: [Your app’s IP address]
- Source port: 3306
And then the defaults are largely good enough. Let me know in the comments if there are even more things that I could lock down – I think have the IP address locked to one I’m expecting should be safe enough though.
Once you’ve saved and applied those new rules, you may be able to telnet to your MySQL server now. You’ll see what definitely looks like a MySQL prompt.
If not, there’s another debug tool you can use: tshark. I’ve found this to be super helpful when trying to track down malicious looking traffic I had one time on a server of mine. In this case though, you can run it on your MySQL server and see if the server is even spotting the
tshark -ta -n port 3306
This’ll show you data being sent to that port. Try and telnet again, you should see some traffic. If not, your iptables rules are wrong, or you’re mistaken about your IP address.
If all is going well though, you should see the traffic from your
This is where I got stuck for a little while, but eventually found that MySQL doesn’t listen to the wider network – only internal network comms. You can fix this in your my.cnf file (likely
bind-address = 0.0.0.0
Restart MySQL, and you should be able to access it all you need.
This is a debugging technique which I imagine many developers just do in their head. I’m afraid I desperately lack the attention span though, and so find this method of debugging inscrutable anomalies really useful.
Here’s a simple breakdown, of what’s really a very simple system.
Ask a question to yourself, and write it down. The question should be about the problem you’re experiencing and should start very basic. It should question a premise which you expect to be true. More often than not the first question should be “does this bug still exist?” (Forcing yourself to see the bug is something that a surprising number of developer don’t do – jumping straight into the code instead.) Next to the question draw a checkbox. Later on the question might be “is the form sending the full file path?”
Do what you can to answer the question. This should be your only goal for the moment. Don’t get distracted by potential other avenues the bug could be hiding down. Even if you spotted something that looks worthwhile to follow. Just try to answer your question in the affirmative or otherwise. There’s no reason to skip over an obvious questions if it only takes a few moments to answer – you’ll just lower confidence in the rest of your debugging journey.
The reason to not get distracted is that you’ll forget how far you got with the first line of debugging. When the distraction turns out not to be correct, you’ll have no idea how to get back onto the track you were on ten minutes ago.
Write down the answer, and then tick the box. Writing down the answer is important for a number of reasons.
First off, if you’re debugging a particularly messy situation you’ll quickly forget the answer to the previous question, leaving you with fewer clues.
Second, and more importantly, is that writing is dog slow. You’ll be pausing, hands away from the computer, and giving yourself time to process what you just learned. Maybe you’ll realise that you’ve been thinking about it wrong, or that you’ve been debugging the wrong thing for the past half an hour. It’s very easy to get swept up in the flow of data when your head is keeping track or every bit of state.
This is also really important whilst pairing. Your partner may not be keeping up – or maybe you’ve decided something wrong. Having it written down is a lot clearer than “well the previous revision is overridden by the next revision because the author of the previous, uh, no, the next revision is the same as the first revision, see?” Write it down so that there’s always a checkpoint for your pair to catch up. If they’re a good pair they’ll ask you to explain anything that looks odd.
Ticking the box is important too! I’ve been lost on many two day long debugging sessions, which left me drained and stressed. Although slowly making progress, there’d be no specific point to celebrate. Instead, now that we have tiny units of work to complete, each tick is a mini-celebration.
Ask the next question.
Keep doing this until you realise, “dammit, it’s just a typo!”
At the end of this, not only will you have fixed your bug, but you’ll have learn a lot about your system, with some semi-decent notes.