A code post! How novel!
Yesterday I was catching up on my blog reading and I ran across Casey Liss’ Shell → Watch Notifications. I love the idea – but it’s a bit of a kludge to put together as-is.
You’ve got a shell script, running a php script and then curl, to a local Node server, which then proxies a call out to the Pushover API. Casey’s using the tools he knows (the hard part is really all in the javascript) and what he’s got works great.
I just don’t want to run a server locally to ping another server – let’s just consolidate all this. At the same time, a lot of folks don’t realize that PHP can be used directly as a shell script. And, since PHP has a kitchen-sink mentality, you can use cURL directly from PHP. So let’s put it all together with the help of the best HTTP / API testing app ever, Paw!
Here’s how I set up the initial request in Paw:
And here’s the code that Paw generated for PHP:
<?php
// Get cURL resource
$ch = curl_init();
// Set url
curl_setopt($ch, CURLOPT_URL, 'https://api.pushover.net/1/messages.json');
// Set method
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
// Set options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// Set headers
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/x-www-form-urlencoded; charset=utf-8",
]
);
// Create body
$body = [
"message" => "This is a test message",
"title" => "Done",
"token" => "your-app-token",
"user" => "your-user-token",
];
$body = http_build_query($body);
// Set body
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
// Send the request & save response to $resp
$resp = curl_exec($ch);
if(!$resp) {
die('Error: "' . curl_error($ch) . '" - Code: ' . curl_errno($ch));
} else {
echo "Response HTTP Status Code : " . curl_getinfo($ch, CURLINFO_HTTP_CODE);
echo "\nResponse HTTP Body : " . $resp;
}
// Close request to clear up some resources
curl_close($ch);
Awesome. Now we’ve got a PHP script that can send a hard-coded message – assuming, of course, that you replace your-app-token
and your-user-token
with your relevant Pushover account details. Let’s adapt this into something we can run from the shell and pass arguments into.
First up, I’m going to paste the above into a file called finished
. For me, I put it in my ~/bin
directory, because I’ve got that added to my $PATH
– meaning I’ll be able to run this script from anywhere. While I’m there, I’ll do a quick chmod +x
on it in the shell, so it becomes executable.
At the top of my new finished
script, I’ll put the magic incantation that helps your shell know this is PHP:
#!/usr/bin/env php
<?php
That hash-bang line tells the shell to fire up the PHP interpreter. After that, the remaining PHP file gets executed automatically. Although, PHP being PHP, you still need the <?php
in order for the interpreter to, well, interpret. Otherwise it will just spit out your code back to you as plain text. Try it, it’s hilarious.
Now you’ll be able to run finished
on the command line and get your hard-coded message. Let’s take the arguments from the command line to turn that into the message. In a PHP shell script, $argv
will be automatically available as an array of all the arguments passed into the script – including, up front, the full path to the script itself. Here’s how we turn that into the $message
string at the top of the file:
$script_path = array_shift($argv); // This pops the script path off the front of the $argv array
$message = implode(' ', $argv); // Concatenates the array together with spaces
And then I modify the $body
array that Paw gave us:
...
$body = [
"message" => $message,
...
And that’s it! Now you can run:
> some --long-running=task; finished The long running task finished
Side note: I don’t call the script done
because unlike Casey, I use bash, and in bash done
is a control keyword – so bash just won’t run any script called done
unless I always give it the full path. Meh.