Is it possible to only run a service for the duration that a devShell is open?
In other words, is it possible to have a service automatically start upon nix develop .#foo and then have it automatically stop upon exiting the shell?
Motivation
I’ve been been writing a devShell in which I can play with TidalCycles - a pattern language aimed at live music composition/performance. It works by interacting with SuperCollider, a kind of audio server that performs the sound generation.
I’m wondering if there’s some way I can automatically start SuperCollider when I do nix develop and then have it automatically stop when I exit the shell?
I’ve played with this a bit, here is what I came up with. Using shellHook to start the process and Bash trap to make sure it gets killed when bash itself exits. Posting the full flake.
{
outputs = { self, nixpkgs }:
let
pkgs = nixpkgs.legacyPackages.x86_64-linux;
in
{
devShells.x86_64-linux.default =
let
bg_service = pkgs.writeShellScript "background-service" ''
while true; do
sleep 1
echo "Test 123"
done
'';
in
pkgs.mkShell {
shellHook = ''
${bg_service} &
BG_PID=$!
trap "kill -9 $BG_PID" EXIT
'';
};
};
}
Yeah in general, it’d be nice to have a solution for each of these cases:
Spawn a unique service per devShell invocation. Each service closes when its respective shell closes. Or,
Ensure only one instance of the service is running if there are one of more instances of the devShell active. It closes only when the last devShell has closed.
For 2 you can take the same approach, but use systemd-run, which should be able to help with deduplicating this service as long as you name it Only issue is to find out when we should close, probably just a case of finding the right exit condition for the unit.
I’ve considered this to run a database for developing my application, but I opted to just create a wrapper script using writeShellScriptBin and run that in a separate terminal. This way, i won’t leave database processes lying around and have an easier time to know what’s going on.
Also, the logs will be in that terminal.