1

So I'm trying to set up a systemd service in order to launch a set of files on a daily basis (different types of journals) from directories based off the date. For example a todo list for today would be located in:

~/Documents/Journals/2019/1/23/ToDo.md 

Now the easiest thing to do is to put it in a seperate directory, say today, and then have a bash script move it to the appropriate spot after the last modified time is no longer when it was created, or when the size of the file is larger than the template file. But while that would be easier, I was wondering if it would be possible to write a script to return the directory of the file to be piped through the executed command in the service. Something along the lines of:

ExecStart=/usr/bin/atom | /Path/To/Script/Todays_Dir Todo.md 

which would take the file as an argument and return the directory/file path based off the date (the same way the directory and files are being created).

Is this possible, or should I just stick to the already proposed solution?

  • What already proposed solution? How does the title match the question?: What Exec? Can you add more detail about what you are trying to do? – ctrl-alt-delor Jan 24 at 8:09
  • What are you trying to assign to ExecStart? – ctrl-alt-delor Jan 24 at 8:15
  • the already proposed solution is the one I mentioned earlier in the post: just creating files in a static directory and moving them either based off size or modified date – Joshua Ferguson Jan 24 at 14:38
  • I'm trying to assign something along the lines of ExecStart=/usr/bin/atom /home/user/documents/journal/2019/1/23/todo.md – Joshua Ferguson Jan 24 at 14:40
  • I have added an answer it is a total guess at what you are asking. Please show inputs and outputs. As you have stated it the answer is ExecStart="/usr/bin/atom /home/user/documents/journal/2019/1/23/todo.md". A process is a transformation of inputs to outputs. A process can be characterised by its inputs and outputs. If you give these then we will know what the process is, that you are trying to create. – ctrl-alt-delor Jan 24 at 16:21
2

Yes, you can write directly to the target directory.

You can't really use a pipe directly as part of an ExecStart= command, since systemd doesn't really implement a full shell. But you can invoke a shell explicitly, which would make it work. For example:

ExecStart=/bin/sh -c '/usr/bin/atom | /Path/To/Script/Todays_Dir Todo.md'

But it turns out this is a bit awkward, since Todays_Dir would end up having to run cat to write to the full path of its argument. In effect, you don't really need a pipe here, you just need to determine the name of a directory and run atom with the proper redirect.

Consider instead just implementing everything in a script and running it directly from the systemd unit.

Something like:

#!/bin/bash
set -e  # exit on error
dated_dir=$HOME/Documents/Journals/$(date +%Y/%-m/%-d)
mkdir -p "${dated_dir}"
exec atom >"${dated_dir}/ToDo.md"

And then in the systemd unit:

ExecStart=/Path/To/Script/GenerateMarkdownToTodaysDir.sh

The exec at the end of the shell script makes the shell replace itself with the atom program, so that systemd will end up running atom directly after setup. For this case it's not that important, so it could be omitted (especially if you're interested in doing some kind of post-processing after the atom run.)

  • well actually that's what I did, but it's multiple files, being launched at different parts of the day. So, I need a timer and service for launching each individual file. – Joshua Ferguson Jan 24 at 3:51
  • @JoshuaFerguson How about a script that takes arguments, or looks at the environment, or checks current time to decide how to act? – filbranden Jan 24 at 3:58
  • well, I'm an idiot. thanks for the Idea, I'm not sure why I thought the that piping a script through a command in a service would be the simplest solution. – Joshua Ferguson Jan 24 at 4:10
  • @JoshuaFerguson You're definitely not an idiot! Using a pipe was a nice idea, but as mentioned would end up with you piping through cat and since systemd units don't understand pipes directly you would end up having to use a shell script instead... Anyways, I hope the answer was useful to you and helped you figure this out without having to maintain tons of separate units for the multiple timer triggers. If you stumble on other issues, ask more questions here, hopefully you'll get more useful advice! Cheers! – filbranden Jan 24 at 23:28
0

You say “I'm trying to assign something along the lines of ExecStart=/usr/bin/atom /home/user/documents/journal/2019/1/23/todo.md”, so the obvious answer is

ExecStart="/usr/bin/atom /home/user/documents/journal/2019/1/23/todo.md"

But I guess this is now what you want.

If the /home/user… comes from the command then you can do

ExecStart="/usr/bin/atom $(command)"

or

ExecStart='/usr/bin/atom "$(command)"'

to lazy evaluate it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.