How to make `nix-shell` clean up after itself?

For example, if PostgreSQL is started for a dev environment, it will keep running when exiting the shell, or when arbitrary files are created in shellHook that are not needed afterwards.

Somewhat perplexed that I was only able to find Killing background processes started in nix-shell, after 15 minutes of searching. Maybe I was looking at the wrong places.

Are there better/more canonical ways to do this?

Thank you!

UPDATE: See an annotated version with inline bash commands to trap here.


shellHook =

  let
    # NOTE These are equivalent.
    #
    #      shellHook =        shellHook =  
    #        ''                 ''         
    #          trap \             trap \   
    #          "                  "        
    #        ''                   echo lofa
    #      + ''                   sleep 2  
    #          echo lofa          echo miez  
    #          sleep 2            " \      
    #          echo miez          EXIT     
    #        ''                 ''         
    #      + ''               ;            
    #          " \
    #          EXIT
    #        ''
    #      ;

    # Helper function to achieve the same
    cleanUp =
      shell_commands:
        ''
          trap \
          "
          ${ builtins.concatStringsSep "" shell_commands }
          " \
          EXIT
        ''
    ;

  in

    cleanUp [
      ''
        echo -n "POSTGRES CLEANUP START..."
      ''
      ( builtins.readFile ./postgres/clean-up.sh )
      ''
        echo "END"
      ''
    ]
  ;

AFAIK, the answer is manually, or custom scripting.

I’m not sure it’s canonical, but your example is roughly how I do it. I agree it could have more obvious idioms, which would help make it easier to find.

I find a lot of high-level/general searches for anything nix-related somewhat frustrating, so I often end up doing code searches (like this one on github https://github.com/search?q=PGDATA+pg_ctl+language%3Anix&type=Code) to hunt down how others are handling something. I see a lot of variations on the general theme, there.

When I have to roll-my-own scripts for handling for a package that has a canonical service definition in order to tailor it for development work in some shell.nix, I can’t help but think it might be nice if the service/program module abstraction had simple support for running multiple instances with scoping/namespacing.

Reflecting on it now, I imagine this is because nix is cross-platform, but module definitions are platform-idiomatic. Improving the nix-shell experience might be a nice side-benefit to cleaner cross-platform module abstractions…

1 Like