Why does this bash script not work?

I just installed KM as a trial on a Mac.

I can't for the life of me get this simple bash script to work.

export LC_CTYPE=C; < /dev/urandom tr -dc '[:lower:][:digit:]' | head -c${1:-6}; echo

I created a macro to execute a shell script in a file with those contents and display the result in a window.

Usually the result is ... absolutely nothing. No window, no error, no feedback. Both the "Try" button and the keyboard shortcut.

Omitting the LC_CTYPE statement produces an error from tr, for which I get a notification.

In trying everything I can think of I have several times gotten a window with 1-2 characters of output, when there should have been 6.

Honestly it's quite infuriating. Any advice would be most appreciated.

(And yes, the script works fine from a terminal.)

Keyboard Maestro's Execute a Shell Script action provides a vanilla shell instance, uncontaminated by the settings in Terminal.app, and decorated with environment variables corresponding to KM variable names and values.

Terminal.app has a particular configuration of $PATH and other environment variables, which typically constitute dependencies for particular scripts.




Post by CCStone

1 Like

Thanks for the response.

Not sure the terminal shell is "contaminated", but yes, I assumed that the shell spawned by KM did not source my bash configs.

Both executables used are in the path of KM's shell.

In any case I've figured it out. 'tr' references LC_CTYPE, LC_ALL, and LC_LANG. I was setting LC_CTYPE, which is not set by KM. However the other two are set to en_US.utf8 by KM, which was unexpected. Apparently one or both take priority over LC_CTYPE. Setting all three fixes the problem.

I'd still like some way to see an execution log or something. If the command results in no output for whatever reason I can't tell if it's even being run.


I was futzing around before reading your last post, and also spotted that KM is setting LC_ALL.

LC_ALL overrides the other LC environment variables, which is why your LC_TYPE wasn't working. Simplest solution is

export LC_ALL='' LC_CTYPE=C; < /dev/urandom tr -dc '[:lower:][:digit:]' | head -c${1:-6}; echo

although I think it's more "proper" to

unset LC_ALL;export LC_CTYPE=C; < /dev/urandom tr -dc '[:lower:][:digit:]' | head -c${1:-6} &>; echo

If you want to see if the command is being run, for troubleshooting, just bung in an echo "Command Ran" at the end. You could also redirect standard error to a temp file and examine that, etc

Thanks for the investigation!
Yeah, I added some echos for debugging.
I still hope to discover an execution log somewhere!
For the moment, though, it works. Yay!

Can you describe some use-cases for this?

You've stumbled over a very specific problem, which might be considered a bug (wrong! See @peternlewis's post below) -- when a script execution step displays results (in a window or notification), the result only consists of newline characters, and the action's "Trim Results" option is turned on (which it is by default) KM will not display it. Because that's all your macro was doing it looked like it hadn't done anything.

You can easily see that the macro is executing by starting up KM's Debugger with "Pause New Macros" ticked (the default) then running the macro -- its name will appear, you can step into the single action, and the name will disappear as the macro completes with no UI feedback. So an execution log wouldn't get you anything that can't be easily got at the moment.

But if you have some specific purposes for an execution log in mind, perhaps the smart(er than me!) people on the Forum can help?

1 Like

Make sure you are displaying the results, and including any error:

If I do this and run your script I get:

tr: Illegal byte sequence

Yes, changing to LC_ALL resolves the problem.

Yes, Keyboard Maestro sets LC_ALL and LANG to utf8, since utf8 is pretty much universal these days, and ensures proper behaviour across languages. Note that Keyboard Maestro sets this itself in its own environment, which is then inherited by the script unless you set it to something different.

Ensure you enable including errors to see what errors are produced by the script.

1 Like

Ah-ha! And it's "Trim Results" being enabled that suppresses "display results..." when the result only contains newlines.

Awesome, @peternlewis -- simply awesome...

1 Like

I didn't know about the debugger feature, thanks for mentioning it.
That would be enough in this instance.

I vaguely imagine that a log would occasionally be useful in situations like, "wait, did I just trigger that macro that does xx invisible thing?" But that's just me imagining.

This case was particularly difficult because the strings were random.
So sometimes there were errors and sometimes not.

How I wish utf8 were universal! I live in Japan and work at a Chinese company.. sigh.

I can see that would be useful, eg a macro that cURLs an API for data -- if the local data doesn't change it would be good to be able to check if the macro didn't run or if it simply grabbed unchanged info from the service.

That's different from logging every action performed, which is why I wondered.

For the macros you want to track, just add "Append Text to File" actions pointing to a file of your choice -- something as simple as Macro “%ExecutingMacro%” started at %ICUDateTime%yyyy-MM-dd'T'HHmmss% would do it. You can then tail the file in Terminal or, if you give the file a .log extension, you can view it in Console.app (thanks, @tiffle!).

1 Like