systemctl (systemd) Timer onCalendar Unit Goes Into Dead State When Target Service is Stopped

I grabbed some boilerplate off the web to make my systemd timer/service pair work. Worked fine.

ie,

systemctl enable myThing.timer

systemctl enable myThing.service

systemctl start myThing.timer

#do not start myThing. service or it will run immediately, that's ok at some other time for a special non-timer purpose.

Showed a nice schedule with 'status' and it ran correctly at the right time.I did some debugging and experiments to tune the system and, after seeming to work ok, it started telling me that the timer was dead. I could find no reason for a long, harrowing debug session.

Here is the answer.

I had started the process by implementing the timer/service pair pointing at a trivial test script. It ran and quit instantly. I did not notice that it was running and quitting on timer start. I also think that I (incorrectly) did "systemctl start" on the quick test service which then exited normally.

Later, I wired it up to my real process, one that takes more than an hour to execute. Of course, I don't want to wait that long so I did "systemctl stop".

After that, the timer would not work. It said it was dead. I tried everything.

The problem is that the boilerplate I grabbed included a "Requires" statement in the Unit stanza. It was set to the same name (myThing.service) as the target service so I did it too. That was an error. I do not know why the boilerplate author included it but requiring the target.service as a dependency makes no sense even though it basically worked.

When I did systemctl stop the long-running target service, that put it into a state where the dependency was not able to be met. Not entirely sure what the difference between never run and stop is but, I have proven this.

When I removed the extraneous 'Require' statement, that dependency went away, the timer started correctly and all was happiness and unicorns.

What I still don't know (Hey, Smartypants, that's what comments are for) is why stopping the target service made it violate the Require constraint.




GITLAB SSH key won't work, asks for password

We are using a locally hosted instance of gitlab. It's a nice program and are enjoying many things about it.

Most of the people working on it live a fairly simple life. I am not one of them. I work a zillion servers and SSH all over the place. I have many RSA keys for various purposes. To keep track of them, I used the comment section of the public key to let me know which one is which.

EG, a public key might end

...SSCtQUvSJ5jdfW9YB3w== mySpecialKeyName

Time came to move a repo from github to gitlab. I grabbed the public key I was using for github and pasted it into the settings of gitlab. It accepted it happily.

Also, it did not work. When I tried to push my newly re-origined ("git remote add origin git@...") repo to git lab, it asked me for a password. There is, of course, no password nor should it ever ask for one.

After trying EVERYTHING, I noticed instructions in the gitlab page that reminded me to copy my public key completely. It said from ssh-rsa to the "email address".

I changed it to

...SCtQUvSJ5jdfW9YB3w== tq@myGitlabEmailAddress.com

And it worked.

You're welcome.

PS, Gitlab, if you ever hear about this: This is bullshit. There is not a single annotation anywhere. Even if I was in the habit of using the RSA key comment section for an email address, there's no reason to imagine it would be the right email address. If you're not going to make *me* responsible for establishing the connection between the key and my account, at least do me the solid of giving me an error message when it doesn't have the right info.






Use iTerm2 for bbedit 'Go Here in Terminal' function

Obviously, nobody wants to use Apple's Terminal in a world where there is iTerm2.

It's equally obvious that Barebones bbedit is awesome.

If you want the context menu selection, Go Here in Terminal to open in iTerm2, paste this into the command line:

defaults write com.barebones.bbedit TerminalBundleID "com.googlecode.iterm2"

(Make sure the quotes weren't made curly by your web browser. You can use bbedit->Text->Straighten Quotes to make sure.)



macOS Will Not Save Mail Signatures

I've been going crazy. I need to change my company email signature. I do so, it works fine but next time I quit Mail.app it goes away. I messed around with plists and permissions. Nothing helped.

Then I found an article HERE.  It had the answer. I repeat it here for posterity.

The problem arises from some bug between Mail.app and iCloud Drive. The problem has been around at least since 2017. There does not appear to be a fix that will make Mail.app save signatures as long as it is involved with iCloud Drive. Fortunately, you can turn that on and off with no apparent harm.

Go to System Preferences->iCloud Drive, then click on iCloud Drives Options... button. In there, you will see a list that includes Mail. Uncheck Mail.

(Note: Mail appears in the list initially shown when you open the iCloud preference panel. This is not the correct one to uncheck. You need to click into iCloud Drive Options and uncheck Mail there.)

Back in Mail.app, you will find that signatures save correctly. Do your work. Quit Mail and reopen and you will find you new and changed signatures in place. Win!!

Once done, you can return to the iCloud Preference Panel->iCloud Drive->options and recheck Mail. Signatures will remain. Life will be good.

Nodejs 10, Readable Stream (close, end, etc) Events Not Being Called


The context is that I had a request to add a feature to a Nodejs app that I wrote a couple of years ago. The purpose of the app is to grab a bunch of files off of an SFTP server and make files out of them. The purpose of this post is to provide a google friendly summary so nobody has to spend as much time on this as I did.

So, I fired up the app on my development machine. It looked ok at first but then it just stopped processing. Further investigation told me that the downloaded files got to disk and that the problem was that the ‘close’ event was never firing.

Inspiration strikes and I realize that the app was written for an older version of Nodejs. More experimentation revealed that the app runs correctly on versions up to 9.11.2 but at 10.0.0, it fails. For google, I restate: upgrade nodejs to version ten causes readable stream to never fire ‘close’ (or ‘end’ or any other) event.

After a full day and a half of research and experimentation, I learned that, starting in nodejs 10, readable streams default to ‘pause’ mode. Previously, they were in ‘flowing’ mode. In ‘pause’, the stream waits for the consumer to take data before it does anything else.

Well, sort of. It does provide the data, somehow. After all, my zip files were created and did work correctly.

In any case, I found a clue someplace that there had been a change to the default for streams. I found another clue that talked about the ‘paused’ behavior. Eventually I found a comment on stackoverflow (here) that mentioned read();

So, here’s the code:

sftpControls.sftpConnection
    .get(remoteDirectoryPath + name, false, null)
    .then(zipSourceStream => {
        const filePath = `${zipFileDirPath}/${name}`;
        zipSourceStream
            .pipe(qtools.fs.createWriteStream(filePath, { encoding: null }))
            .on('close', () => {
                zipSourceStream.destroy();
                next('', name);
            });
        zipSourceStream.read(); //tell the stream to be ‘flowing’
    })


That is the entire change. Add one read() and the stream becomes ‘flowing’ and emits a close event when it’s done.



A small warning. I tried to chain the .read() along with the pipe() and on() methods. That failed. The read() method does not return the source object. You will get an error, “no read().pipe()”. Reverse it and get “no pipe().read()”. You have to run it like it’s shown, directly off of the original stream object.

If anyone reading this actually understands why this is happening or how it works, I am sure future programmers will be grateful to read the comments. I know I will.



Using an asynchronous function inside a synchronous one - NOT!!

tl;dr: You can't. At least not in Javascript. (I beg you. Prove me wrong in the comments!)

Here's the problem I face.

I have a template system I use. It relies on a .ini file that has all the parts of (in this case) an email message. Subject, text body, html body, etc. It replaces tags in the elements with properties of a supplied object of the same name. The template also includes a property called 'transformations'.

Transformations contains a set of properties whose values are functions. When processing the replacement, my system runs the transformations against the other replacement properties and adds the result for replacement in the template. It's useful for making sure that names are capitalized or adding dates or changes to html styling based on the data.

The new challenge is that I need to have a transformation that gets a result from the database. The problem is that the database access is asynchronous. The system is set up to run simple string processing synchronously. There is no callback option.

I spent an entire day screwing around with generators/yield, async/await and reading what felt like the entire internet looking for an idea of how to deal with this. I consider putting the database function into code, per se, to be a crime. (I do not mind calling a specific system function but it has to be called from the primary locus of control, ie, the template. I don't want someone to look up later and find that the result is just not there anymore with no clue where it should have come from.)

I ended up adding a property to the template called 'asyncronousTransformations' and having the program that uses the template process them. This required back filling asynchrony several levels up the code. As you might imagine, sending email is asynchronous but the (hitherto) simple string processing was not. Now it is.

How to turn off the Tap to Wake feature on your iPhone X

My iPhone has been a huge pain in the butt since iPhone X made it so that it thought my nipple under my shirt pocket is a finger that required it to do whatever my nipple wanted to do.

No more!! This article explains, settings->general->accessibility->tap to wake!! Disable it and my nipple is no longer empowered to hang up my phone calls.

And, it's harmless because settings->display & brightness->raise to wake makes it so that it almost always automatically wakes up when I want it to.

Salvation.

read more: How to turn off the Tap to Wake feature on your iPhone X

Tue May 29 2018 12:56:23 GMT-0500 (CDT)

Missing req.body received from nodejs/npm request.post() call

This is almost trivial unless you forget about it and try to research the solution. It's stupidly obscure, probably because it's so trivial.

I am using request to post into some application. I didn't have a convenient boilerplate to reference and the damn internet did not provide a decent example. Here is a working and completely adequate post block:

    request.post(
        {
            url:url,
            headers: {
                authorization: `${userId} ${authToken}`,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ propertyName:'propertyValue' })
        },
        (err, response, body) => {
            console.dir({ 'err': err });
            console.dir({ 'response': response });
            console.dir({ 'body': body });
            //callback(err, body);

        }
    );

This works but it didn't at first. On the receiving end (also nodejs, using express), the call was just fine, came back 200, showed its presence on the far end but, absolutely no post body content. The problem? I had forgotten to include the Content-Type header.

Easy but, since I forgot about it, I needed some help. Unfortunately, the internet was not so helpful. Eventually I did find a clue but, hopefully I've said enough here that google was able to help you learn this a lot more quickly than I did.

Public Key Encryption Playground

My interest in public key encryption continues. I wanted to be able to actually use a tool to play  so I wrote one.

It does these things:

1) Generate a key pair.
2) Extract a public key from a private key.
3) Manually enter public or private key.
4) Create a crypto text string from plain text input.
5) Extract plain text from a crypto string.


You can play with this at: http://genericwhite.com/rsaEncryptionDemo/

Here's a brief video to get started...



Code is available on github.