Hey I want to add a command to my system. I am not using any package-format or anything. I just want to install a script that I wrote.

I know of some ways to do that:

  • add my script into whatever is the first thing in $PATH
  • add a custom path to $PATH (in /etc/profile.d/ or /etc/environment) and put the script into the custom path
  • add my script into /usr/bin or /usr/local/bin

I remember reading that profile.d/ doesn’t get picked up by all shells and that /etc/environment (which exists but is empty on my system) shouldn’t be used.

What should I do to ensure that my command will be available everywhere on any gnu/linux or bsd system?

EDIT: I should clarify that I am asking this only out of curiosity. I just like knowing how this stuff works. The script was just an example (I thought this would make it easier to understand, lol). I am interested in knowing a way to install a command without any chance of that command later not being found by other programs. I find many different answers to this and they all seem a little muddy, like “doing x should usually work”. I want to know the solution that always works

  • ZeroEcks@lemmy.ml
    link
    fedilink
    arrow-up
    31
    arrow-down
    1
    ·
    11 months ago

    I always add ~/.local/bin to my path then throw binaries in it. I do however make sure it’s last on my path so it can’t overwrite system packages, say maliciously…

    • flubba86@lemmy.world
      link
      fedilink
      arrow-up
      10
      ·
      11 months ago

      That’s a good point about it going last in your PATH. Malicious applications running as non-root can still install payloads to ~/.local/bin and hijack common system functions.

      • ZeroEcks@lemmy.ml
        link
        fedilink
        arrow-up
        6
        ·
        11 months ago

        Yeah, consider a script named Sudo that reads as follows

        sudo virus-payload && sudo "$@”

            • Alex@feddit.ro
              link
              fedilink
              arrow-up
              2
              ·
              11 months ago

              The first one only runs the actual command after the virus payload finishes, and only if it succeeds. The second one runs both almost at the same time

        • IAm_A_Complete_Idiot@sh.itjust.works
          link
          fedilink
          arrow-up
          4
          ·
          11 months ago

          Only for it’s child processes, e.g. call a bash script with a modified PATH. Still problematic though.

          …I suppose they could also modify your .bashrc equivalent.

  • elmicha@feddit.de
    link
    fedilink
    arrow-up
    32
    arrow-down
    2
    ·
    11 months ago

    Don’t put it in /usr/bin, that’s where your package manager puts executables, not you. Other than that, do what you want. /usr/local/bin is good, or if it’s only for your user ~/bin, ~/local/bin or ~/.local/bin - I don’t care. Also just let your users decide where they want to put the script.

    • niemand@discuss.tchncs.deOP
      link
      fedilink
      arrow-up
      3
      arrow-down
      1
      ·
      11 months ago

      So are you saying that /usr/local/bin exists on every gnu/bsd system and when I put a script in there it will always be available for all users, without any chance of this not working (eg. “command not found”) and no need to reboot my computer or anything? Also, is there a good reason not to put it in /usr/bin?

      • folkrav@lemmy.ca
        link
        fedilink
        arrow-up
        9
        arrow-down
        1
        ·
        edit-2
        11 months ago

        He just told you why not to put it in /usr/bin: it’s where your package manager puts executables.

        I’m not too sure why it’s important where your users put your script from a script author perspective? Otherwise, just check the default $PATH content for a fresh user on said system, and put it somewhere in there.

        • niemand@discuss.tchncs.deOP
          link
          fedilink
          arrow-up
          6
          ·
          11 months ago

          He just told you why not to put it in /usr/bin: it’s where your package manager puts executables.

          I thought he might tell me why me and my package manager cant both use this directory. The reason for that is not obvious to me

          • chickenf622@sh.itjust.works
            link
            fedilink
            arrow-up
            5
            ·
            11 months ago

            Cause it’s good to know of something is an installed package at a glance. I also imagine it would reduce the risk of accidentally overwriting your own scripts if the packages happen to have the same name as your local scripts.

          • folkrav@lemmy.ca
            link
            fedilink
            arrow-up
            4
            ·
            11 months ago

            Other people already answered you, but it’s mostly for:

            1. Keeping things obvious, you know who did what
            2. Avoid potential collisions
          • aperson@beehaw.org
            link
            fedilink
            English
            arrow-up
            4
            ·
            11 months ago

            Because in situations like this, segregation is a good thing. You don’t want automated tools futzing in directories that you might have wanted to keep as-is.

          • InverseParallax@lemmy.world
            link
            fedilink
            English
            arrow-up
            2
            ·
            11 months ago

            Unix has had a long running convention of separation between “operating system” and other files, so you can blow away something like /opt or /home without making your system unbeatable.

            If you stick stuff under /usr/bin then you have to track the files especially if there are any conflicts.

            Best to just add another path, I use ~/bin because it’s easy to get to and it’s a symlink from the git repo that holds my portable environment, just clone it and run a script and I’m home.

            • andruid@lemmy.ml
              link
              fedilink
              arrow-up
              2
              ·
              11 months ago

              And migrate /opt and /home (or even remotely mount) so that user data is preserved outside of the system!

              Both features make system admin much more sane!

  • z3bra@lemmy.sdf.org
    link
    fedilink
    arrow-up
    10
    ·
    11 months ago

    For it to always work, you should put it in /bin. Every other solution may fail in some corner case.

    Don’t do this though.

    The correct way to install a command is to package it for your distro, and put it in a place that’s suitable for its usage.

  • hallettj@beehaw.org
    link
    fedilink
    English
    arrow-up
    8
    ·
    edit-2
    11 months ago

    There are specs for that!

    For system-wide installation the Filesystem Hierarchy Standard essentially says:

    • put it in /usr/local/bin/ if you want to drop a script somewhere
    • or put it in /usr/bin/

    Both should be in the default $PATH for most systems.

    For single-user installs the XDG Base Directory Specification says,

    User-specific executable files may be stored in $HOME/.local/bin. Distributions should ensure this directory shows up in the UNIX $PATH environment variable, at an appropriate place.

    Those locations will work in 99% of cases.

    Nothing will work for every case because Linux systems are many and varied. For example I’m on NixOS which doesn’t adhere to that particular provision of XDG, and doesn’t adhere to any of FHS.

  • cbarrick@lemmy.world
    link
    fedilink
    English
    arrow-up
    7
    ·
    11 months ago

    If you are against packaging, then the right way to do this is to put the command somewhere and set your PATH.

    For manually managed stuff, the typical places to put commands include:

    • /usr/local/bin
    • /opt/something/bin (where something is different for each project)
    • ~/bin
    • ~/.bin
    • ~/.local/bin

    To set your PATH, it depends on what shells you want to see your command. Here’s a good guide: https://askubuntu.com/questions/247738/why-is-etc-profile-not-invoked-for-non-login-shells

    • InverseParallax@lemmy.world
      link
      fedilink
      English
      arrow-up
      1
      ·
      11 months ago

      Fyi /usr/local/bin is for system wide applications, freebsd and it’s friends use it for non-core software installs.

  • popcorp@discuss.tchncs.de
    link
    fedilink
    arrow-up
    3
    ·
    edit-2
    11 months ago

    $HOME/bin or /usr/local/bin depending on whether you want to make it available for a single user or for everyone

    And check your $PATH of course

  • TootSweet@lemmy.world
    link
    fedilink
    English
    arrow-up
    3
    arrow-down
    1
    ·
    11 months ago

    Don’t discount the option of actually building a package for it. I’m not running BSD, but I’ve built/installed packages for multiple “scripts” I’ve written. I like how “clean” it is.

  • pooberbee (any)@lemmy.ml
    link
    fedilink
    arrow-up
    1
    ·
    11 months ago

    Either #2 or #3. /usr/bin and /usr/local/bin exist for that purpose, but some people prefer to keep personal scripts and such in home, maybe as part of a dotfiles repo or something, and so just add ~/.dotfiles/scripts or something to PATH.