One of the great advantages of tsm is that it is a fully functioning shell / command-line system that works the same on Linux or Windows. Finding the commands to do what you want to do in Tableau – that’s the easy part these days. But both Windows and Linux have their own quirks, especially when you want to fully automate a process. This post discusses how to get things working on Linux – if you need to automate on Windows, take a look here.
Shell scripting on Linux, particularly when you want to schedule using cron, have a lot more quirks than you’d think at first glance. It’s very common for the same set of commands you just typed in to not work at all when you put them in a shell script. And even then it may still fall over when run via cron. To run tsm commands from a script, we have to make sure our environment is always specified correctly.
The shell script
#!/bin/bash PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:usr/bin:/sbin:/bin" export PATH source /etc/profile.d/tableau_server.sh tsm maintenance cleanup -l # any other tsm commands or other bash commands
You’ll notice that the script has several lines before it gets to any tsm commands. Without them, you’ll get a message like:
line 3: tsm: command not found
The early lines tell the the operating system how to set up the environment, which is essential because it’s possible the script is run in contexts where the environment is different than the interactive shell you are logged into.
The first line tells it to use the BASH interpreter, rather than the most basic shell. This might not be necessary just to run the tsm commands, but it will pay dividends if you are doing anything more complex along with it. The PATH lines similarly aren’t necessary in the most basic versions, but might be for any other Linux commands you expect to run.
The essential line is the source command, which I discovered by looking at this Knowledge Base article. You will note that my version required ‘.sh’ at the end of the file, rather than how it is listed in the KB.
The source command is telling the interpreter to run things using the Tableau Server configuration, which makes the tsm command available.
After that, we can put whatever tsm commands we’d like, or any other scripting protections.
Once you’ve saved your file (mine is called cleanup_ts.sh), remember you need to make the shell script Executable using chmod:
chmod 755 cleanup_ts.sh
755 permissions lets anyone execute but only the creator can edit. This is the standard permissions settings you’ll see in most Linux documentation but other permutations may be more appropriate for your given situation.
The cron job
cron let’s you schedule commands to be run on repeating schedules, but it is even more finicky about environment settings than a basic shell script.
The command to modify your cron schedule is
which will use the editor for your platform (most likely defaulting to vi but it just depends on the flavor of Linux and previous choices.)
This is the crontab I ended up with that actually worked. It is running the cleanup_ts.sh script from before, which works when called from the command line (which includes the source command). But notice I still have to call the source command in the cron job, and then chain it together with the script itself using the && operator.
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:usr/bin:/sbin:/bin" SHELL="/bin/bash" 0 8 * * 0 source /etc/profile.d/tableau_server.sh && /home/ec2-user/cleanup_ts.sh >> /tmp/cleanup_ts_log.txt 2>&1
Why doesn’t the source command in the shell script itself work? I don’t know — but I can tell you that if you are having commands that don’t work correctly in your shell scripts, but only when run via cron, you should try solving it by setting the environment context (PATH, etc.) upstream in the cron job before running your script.
You’ll note there is a log file receiving all of the output and error output from the cron job (the part starting with >>). If you don’t do this, you’ll never know what is going wrong. I also recommend running the job very frequently while debugging errors — the timer part was set to
*/2 * * * *
while I was working to get everything set up correctly. This let me make a change, cron would quickly run, then I could check my log file.