0

How do I make a script that I made myself that I already put in my path and made executable usable with sudo? (Xubuntu 22.04.1.)

The script is located here: ~/bin/myScript.

When, from an arbitrary directory, I do

sudo myScript

The error I get is this:

sudo: myScript: command not found

3
  • 1
    Does this answer your question? why is sudo not working with exported path?
    – mook765
    Commented Oct 27, 2022 at 2:15
  • @mook765 Thanks, I didn't see that one. It answers the why (and gives one explanation of how to do it), but this question is about the how specifically, and nothing else. (So answerers don't have to address the why every time they answer with more solutions.) Commented Oct 27, 2022 at 2:18
  • When using sudo you should use the full path to the script, i.e. if in your home ~ directory it would be sudo bin/myScript or sudo /home/user/bin/myScript.
    – Terrance
    Commented Oct 27, 2022 at 2:23

1 Answer 1

0

There are a number of ways to do this.

  1. Use absolute paths instead of relative paths (this defeats the purpose of having it in your path, though).
  2. Make a separate script that invokes sudo and converts things into absolute paths.
  3. Add your script to the system with update-alternatives.
  4. Put your script in a different path that is meant for this sort of thing (it'll be a system path--not one in your home directory).
  5. Add a new path (whether or not it's in your home directory) to be the sort of path needed to do this sort of thing. You'll need to have an understanding of the underlying security reasons for things if you do this.
  6. Invoke sudo from your script itself (instead of outside of it). Same goes for aliases and functions.

While #4 and #5 may work, I don't think most people want to bother with that, as it might butcher your system and open you up to security vulnerabilities if you do it wrong; plus there's a learning curve (and I don't know all the ins and outs of that, yet). So, I'm going to give you a simple non-invasive solution using #2, and then I'll tell you how to do #3.

Okay, here's a Python 3.x script that I wrote; I just called it sud and put it in ~/bin (in Ubuntu, that will automatically put it in your regular path; you don't need to put it in an ultra special path usable with sudo). The script essentially invokes sudo and has it do what sudo does. However, if you want to invoke your own script that is in your regular path, preface it with a comma (to make it turn it into an absolute path to your script), and preface regular relative paths that aren't in your path with a + (to turn them into absolute paths to your files); be sure to do chmod u+x ~/bin/sud (to make it executable for the current user; for security reasons, there's probably no sense making it executable for anyone else as chmod +x and chmod a+x do). Yes, you can unambiguously use flags and options with sudo and the calling program this way.

#!/usr/bin/env python3

"""
This is like sudo, except it finds the absolute paths for scripts if they begin with a comma, and it finds the absolute paths for filepaths if they begin with a plus. It also uses an absolute path for sudo. The aim is to allow a flexible way for all scripts in the path to be run with sudo, while keeping the user conscious of which ones don't naturally run with sudo.

It should also be able to be used like sudo for the uses that sudo already works for. Obviously, it will cause problems if your files or commands begin with + or , naturally. So, don't use it on those.

Example usage:
sud ,myscript
sud +mypath
sud ,myscript +mypath
sud app
sud app path
"""

import subprocess, sys, os, shutil

sys.argv[0]=shutil.which("sudo")

i=1
while i<len(sys.argv):
    if sys.argv[i].startswith(","):
        sys.argv[i]=sys.argv[i][1:]
        sys.argv[i]=shutil.which(sys.argv[i])
    elif sys.argv[i].startswith("+"):
        sys.argv[i]=sys.argv[i][1:]
        sys.argv[i]=os.path.abspath(sys.argv[i])
    i+=1
subprocess.run(sys.argv)

Okay, now the update-alternatives option. This requires root privileges initially. It also puts your script in your path (so you can put it wherever; it doesn't have to be in your path first). It also makes the script available systemwide, if its location is available systemwide. Don't move your script after you do this, or it'll break the command.

First of all, choose a name for your script that isn't in use on your system (otherwise this will be more complicated and I'm not going to bother explaining how to handle the more complicated stuff right now).

Add the following lines to your ~/.bashrc file:

enter() {
    sudo update-alternatives --install /usr/bin/"$1" "$1" $(realpath "$1") 0
}

Save and exit. Exit the terminal and open another one. Now, whenever you type enter myScriptName (be sure you're in the same directory as it when you do it, and use a relative path that is only your script name) it will add that script to your path in a way that will make it usable with and without sudo. Be sure to set your permissions and file location appropriately if you're in a multi-user environment (i.e. probably not in your home directory, and make sure the permissions aren't something like 0600, but rather something like 0555).

If you want to remove such a script from your path after having added it with update-alternatives, do this (it doesn't matter which directory you're in):

sudo update-alternatives --remove-all myScriptName

You can use update-alternatives to add them manually, too, of course, instead of using my enter function above. So, if you want to add /opt/Programs/myScript to your path, you could do this:

sudo update-alternatives --install /usr/bin/myScript myScript /opt/Programs/myScript 0

Then you can type these things from anywhere to invoke it:

  • myScript [myArgs]
  • sudo myScript [myArgs]

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .