I have a script foo.sh located in /home/pi/Documents/Python directory. Purpose of this shell script is to run python script which needs root priviledges as it must reset usb device.
The script is as follows:
#!/bin/sh
export PATH="$PATH:/home/pi/.local/lib/python3.7"
python3 /home/pi/Documents/Python/foo.py
When I run the foo.py from Midnight Commander (setting a cursor on the file and pressing enter) it works, it exports the path correctly and the python script fails as it does not have enough priviledges to reset usb device.
I have actually made this script to run python script under root, but the root needs set a path to used module first.
However when I run
sudo foo.sh
I receive an answer:
sudo: foo.sh: command not found
I have checked the permissions and the foo.sh file has -rwxr-xr-x
sudo python3
typed in terminal also works correctly and opens python interpreter.
What is the problem that causes wrong behaviour under sudo?
I might be mistaken (I don't have a Linux Machine at hand atm, so I cannot verify), but if I recall correctly the user_home is part of the PATH variable exported for that user.
When you use the command sudo you are acting on the behalf of root which has got a different user_home than yours (== the current user), therefore your script is not found in any of the directories listed in the active PATH (the one of root because you are using the sudo command).
However, it should be possible to run successfully the following command:
$ sudo ./foo.sh
I hope this might shed some light.
Unless foo.sh is in a directory shown referenced by the PATH environmental variable, the environment will not recognise the command and hence the error
If you are in the directory with the foo.sh script, execute it with:
sudo ./foo.sh
If you are in a different directory, execute with:
sudo /pathtosh/foo.sh
Related
Hello I need help trying to figure out how to run a shell script in startup. I know that the magicmirror.sh script works and I know it is in the right path. When I reboot my raspberry pi it does not run the script. I have added the line of code to the end of the crontab using sudo crontab -e. The code is as follows.
#reboot sleep 60 && /home/pi/magicmirror.sh
The problem could be the way you call commands in your script.
As the crontab runs from e very minimal shell, not all environment vars get loaded.
So maybe the $PATH var is missing / not fully loaded, so some binary you call from inside the script is not found.
I guess you script starts with #!/bin/bash. If my guess is correct either try to start te script with #!/bin/env /bin/bash (this means "start bash with a full environment") or replace all calls/commands in you script with their full path. e.g. /usr/local/bin/myprog dosomething instead of myprog dosomething.
EDIT:
As #shv mentioned this could ALSO be a problem of permissions. But maybe in a different kind of way. If you run sudo crontab -e you are editing the crontab of root, not of your pi user. This has 2 effects:
you script is run in the environment of root. Sometimes some configurations enable you to do things differently than the root user. I am by no means a Raspberry pi expert, but it could be that your magic mirror accesses some GPIO pins. I can imagine that, although having more permissions to GPIO, root has to interact in a different way with GPIO than your pi user. (wild guess)
This is actually a security risk. Your pi user can edit the magicmirror.sh at will and write anything it it. So for example, someone having access to that pi user (either because he "hacked" the system, or is just someone you gave access to it) could write e.g. rm -rf --no-preserve-root / and just rebooting the device, to clean the filesystem. And you would not want to to that, do you?
To fix this you can either just edit you own crontab with crontab -e (without sudo) or put that script somewhere only root can access (if you need the root permissions) e.g. /root/magicmirror.sh
I think it's an issue with permissions.
try use crontab -e without sudo.
I am building project source code in a SUSE server.
The project build.sh called "lzma" command to compress kernel.
The project build.sh need "sudo" to get access to some system command.
But I has tried to execute "sudo ./build.sh", and the shell always report error: "lzma: command not found."
I could execute "lzma" in shell with my user account. It works fine.
I also write a test shell script named "test.sh" which calls "lzma" command.
I found that it fails with same error message if I excute "test.sh" with "sudo" .
But if I execute "test.sh" without "sudo", it works fine.
Why ?
"Command not found" within sudo is almost invariably the result of an environment variable such as PATH, LD_LIBRARY_PATH (if what's missing is not the executable but a shared library it requires) or the like being altered.
You can pass working values through your environment variables through explicitly:
sudo PATH="$PATH" ./test.sh
Sudo uses a different Path then your user account.
EDIT (see comments)
Try and execute:
type lzma
Say the output reads something like '/usr/bin/lzma', then just copy that output into your sudo command like (for example):
sudo /usr/bin/lzma
That should do the trick. You should also write the full path of lzma into your shell script if you are to run it as root.
EDIT 2:
Or, as Charles Duffy mentioned in his answer, you could leave all things as is and simply use PATH="$PATH" in your command if you are trying to execute your file as SUDO or as a different user.
Consider the following Makefile.
install:
sudo rpi-install.py /dev/ttyUSB0 foo.bin
Note that I have deliberately not hardcoded a path to rpi-install.py because it is not in the same location on other people's machines, but I expect it to be in the PATH of everyone who uses my code.
Unfortunately, when I type make install, I get the following output.
sudo rpi-install.py /dev/ttyUSB0 larson.bin
sudo: rpi-install.py: command not found
make: *** [install] Error 1
When I type the exact same command on my shell, it works exactly as expected.
Additionally, when I remove the sudo from the Makefile, it successfully finds the binary and gets a permission denied error due to lack of root privileges.
How can I allow make to discover the programs that are in my PATH when they must be run with sudo?
For the sake of reproducibility, assume that the following contents are in rpi-install.py, and that it lives in the directory $HOME/bin. Additionally assume that PATH includes $HOME/bin.
#!/usr/bin/env python
print "Hello World!"
There was a combination of two fixes that resolved this problem.
I needed to set PATH in .profile instead of .bashrc because the default shell /bin/sh used by make did not pick up the correct path from .bashrc.
I needed to set the environment for the sudo command inside the makefile explicitly to be the external PATH, based on this answer to this question.
sudo env "PATH=$(PATH)" rpi-install.py /dev/ttyUSB0 larson.bin
I put a custom command (shell script) in /usr/local/scripts/.
In order to see commands from /usr/local/scripts, I set the PATH using the following methods:
sudo visudo
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/scripts"
sudo nano /etc/profile
PATH="$PATH:/usr/local/scripts"
export PATH
sudo nano /etc/login.defs
ENV_SUPATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/scripts
ENV_PATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games:/usr/local/scripts
sudo nano /root/.bashrc
PATH="$PATH:/usr/local/scripts"
export PATH
sudo nano /etc/environment
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/scripts"
And this works in most cases, but...
I have two script which, in their code, calls a script from /usr/local/scripts/, and it can't find my script!
The first is /etc/network/if-up.d/sendip, which is run as root when the networking stack is initialized.
And the second is /usr/local/scripts/notif-login which is run as root from pam by /etc/pam.d/sshd:
session optional pam_exec.so /usr/local/scripts/notif-login
If I run both script from my terminal shell, another user, with sudo, without sudo, after su, or login with root, it works properly. But when it is runner by the system (first when networking initialized, and the second via SSH) both failed to run scripts from /usr/local/scripts.
Is there another place where I have to set the path?
Bash/sh will not read /etc/profile for "non-interactive shells", such as the shells from which the scripts you mention run. I'm not sure which distribution you're using, but you should just be able to add it to /etc/environment's PATH definition. Ob Ubuntu, for example:
Change:
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
To:
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/scripts"
Edit
This should work under Raspbian; it does under Debian. If it doesn't, you might need to just modify the path at the start of one of your scripts. None of the normal startup files will execute for a non-interactive session under Bash. Also try outputting $SHELL and make sure the script is running under the shell you think it is.
I'm new to Linux and I wonder there are many programs we can use only program name to start it in Linux terminal, like gedit,vi,firefox instead of providing the all program's path,I like to run my own programs like this in terminal only typing program name, programs I like to run are written in Java and Python (.jar, .pyc, .py and .class)
I like to know how to do it with step by step
You can write whatever program/script you have to behave as a command. Let's say your executable script/program is named as my_script and is placed in /path/to/my_script.
Be sure that the script is executable. If not,then please do
chmod +x /path/to/my_script
Then, place a symlink to this location in /usr/local/bin as
sudo ln -s /path/to/my_script /usr/local/bin
You can add the symlink to any of the paths mentioned in $PATH.
That's it and enjoy your program.
The other answers all involve creating a symlink in a directory that is already listed in the system PATH, but I think it is more unixy to add needed directories to your PATH.
If your script is located at $HOME/bin/myscript and you have already made sure that it is executable then you can run
export PATH=$HOME/bin:$PATH
to run it without giving the full path. And you can add that same line to your .bashrc file in your home directory to have it preloaded whenever you start your shell. This approach does not require that the user has permission to create symlinks in system directories.
If you have an executable binary file in your home folder (let's say for example sublime_text) you must give it execute permision and call it with its relative path
chmod +x sublime_text
./sublime_text
If you made a symlink to it in /usr/bin (or other folders included in your PATH), you would be able to call it by its name
sudo ln -s ~/sublime_text /usr/bin/sublime_text
sublime_text
In your case, you aren't dealing with binary files, but with scripts meant to be interpreted. For this you must prepend a shebang telling linux what's the binary meant to execute the script. If it was, for example, a python script ~/hello.py, these could be the contents of the script:
#!/usr/bin/python
print "Hello, World!"
Where the first line tells linux to use the python binary to execute the script.
From then on, you can do:
chmod +x hello.py
sudo ln -s ~/hello.py /usr/bin/hello
hello
And it will echo "Hello World" to the console.