Getting bash script to work with shell command

I am trying to get a bash script working but having great problems. Just trying to run simple Linux commands (rm and cp).

I have a script called script.sh which sits in a subdir “shell” under the config subdir and contains the following text

#!/bin/bash
sudo rm /config/blue.yaml
sudo rm /config/hall.yaml
sudo rm /config/kitchen.yaml
sudo cp "/config/Wiser_Schedule_Backup/blue - Copy.yaml" /config/blue.yaml
sudo cp "/config/Wiser_Schedule_Backup/hall - Copy.yaml" /config/hall.yaml
sudo cp "/config/Wiser_Schedule_Backup/kitchen - Copy.yaml" /config/kitchen.yaml

If I putty into home assistant then I can run each one of these lines on its own and it deletes the files fine and when I run the cp command at the prompt it copies the file from the Wiser_Schedule_Backup directory into the main directory and renames it.

However if I try to run “bash script.sh” it does work but just returns the prompt

I have also tried a chmod 775 script.sh

What I have noticed though is that the equivalent number of files appear in teh config directory but consist of random letters (e.g. CG3BBD~O) and the contents are the contents of the files I am trying to copy. Feels like it is some kind of permissions issue.

Once I can get this running as a script file I will then try to add it to an automation but even at this basic level I am struggling to delete and copy files.
What am I doing wrong?

TIA
lcsneil

Setup
|Version|core-2021.3.3|
|Installation Type|Home Assistant OS|
|Development|false|
|Supervisor|true|
|Docker|true|
|Virtual Environment|false|
|Python Version|3.8.7|
|Operating System Family|Linux|
|Operating System Version|5.4.83-v7l|
|CPU Architecture|armv7l|
|Timezone|Europe/London|

Try giving the script the full path of the cp and rm commands.

What do you mean by saying it just returns the prompt?
Your shell script should not print anything if everything works, so the only thing you’ll see is your shell prompt after the script finishes running.

cp seems to have an option that creates so-called backup files (see man cp), but it should not be enabled by default.

If there were any permission issues, rm and cp would complain (write stuff to stderr).

Try adding the following command between the last rm and first cp. It will wait for you to press the return key. While it is waiting, open another ssh session and verify that the files are in fact gone.

read -p "Done removing. "

You’ll probably need to configure sudo to not ask for your passwords if you want to run this script automatically. Do you actually need sudo? I think HA is running as root in the docker container.

EDIT: Please clarify where you are running the script. Your HA says Docker: true, but the default container does not seem to have sudo at all. Are you running this on your host OS that just happens to have the home assistant configuration directory in /config? If so, don’t expect everything to work exactly the same after you configure HA to start the script (it will be running inside the docker container).

I use some rm shell commands and some rm commands with find and I do not have sudo in any of them (HA Supervised)… also what’s up with the quotes? Can you rename them to something without the spaces and stuff and try without the quotes? I thought cp was just source path destination path separated with a space (although I am no Linux expert)

cp can handle filenames with spaces just fine, you just need to quote them so that bash does not split them into multiple arguments.

I think you are right about sudo. I think OP is testing the script on his host OS, but wants to later run it inside the container.

@ondras12345 When I said just returns the prompt then what I actually meant to say was didnt return any errors but doesnt delete the files. (Yes I realise it would be a ‘silent’ script.

Agreed I dont think that these are backup files as their content is the same content of the xxx - copy.yaml file rather than the xxx.yaml file I am trying to delete.

I only put sudo in as it was a suggestion from another thread I had read. Have removed that.

Inserted

read -p "Done removing. "

And checked and it hasnt deleted the files. (Do I have the correct path in there - is the rm relative to where the script is namely config/shel/script.sh) have tried rm /config/blue.yaml and also …/blue.yaml

I have Home assistant running on a raspberry pi4 with supervisor. I am running the script from a putty window into the raspberry pi

login as: hassio
[email protected]'s password:

| |  | |                          /\           (_)   | |            | |
| |__| | ___  _ __ ___   ___     /  \   ___ ___ _ ___| |_ __ _ _ __ | |_
|  __  |/ _ \| '_ \ _ \ / _ \   / /\ \ / __/ __| / __| __/ _\ | '_ \| __|
| |  | | (_) | | | | | |  __/  / ____ \\__ \__ \ \__ \ || (_| | | | | |_
|_|  |_|\___/|_| |_| |_|\___| /_/    \_\___/___/_|___/\__\__,_|_| |_|\__|

Welcome to the Home Assistant command line.

System information
  IPv4 addresses for eth0:  192.168.0.232/21
  IPv4 addresses for wlan0:

  OS Version:               Home Assistant OS 5.12
  Home Assistant Core:      2021.3.3

  Home Assistant URL:       http://homeassistant.local:8123
  Observer URL:             http://homeassistant.local:4357

Basically what I am trying to do via an automation is to delete files in my config directory on homeassistant and then copy files from a subdir back into the top level directory.

Perhaps all of the above is the wrong way about it? Happy to take any alternative suggestions.

lcsnile

Paths that begin with / are absolute paths.
Please show me the output of these commands:

# cd into the correct directory
whoami
pwd
ls -la
cat script.sh
# run your script:
./script.sh  # hit ctrl+c when you get to that read -p "Done removing. " to terminate the script
ls -la

What exactly are you trying to achieve?

If you are using HA OS image HA can already create snapshots of the configuration.

➜  config
➜  config
➜  config whoami
root
➜  config pwd
/root/config
➜  config ls -la
total 517668
drwxr-xr-x   17 root     root          4096 Jul 13 17:12 .
drwxr-xr-x    1 root     root          4096 Jul  3 18:35 ..
-rw-r--r--    1 root     root             8 Mar  9 12:42 .HA_VERSION
drwxr-xr-x    2 root     root          4096 Jan 12 17:15 .cloud
-rw-r--r--    1 root     root          1550 Jul 13 12:55 .sonoff.json
drwxr-xr-x    3 root     root          4096 Jul 13 17:11 .storage
drwxr-xr-x    2 root     root          4096 Jun 28 17:47 Temp
drwxr-xr-x    2 root     root          4096 Jul 13 09:21 Wiser_Schedule_Backup
-rwxr--r--    1 root     root          7165 Feb 28 18:41 automations - Copy.yaml
-rw-r--r--    1 root     root         35958 Jul 13 13:38 automations.yaml
-rwxr--r--    1 root     root             2 Jul 13 13:56 blue.yaml
drwxr-xr-x    3 root     root          4096 Jan 12 17:15 blueprints
-rw-r--r--    1 root     root          8693 Jul 13 14:10 configuration.yaml
-rwxr--r--    1 root     root             2 Jul 13 13:48 conservatory.yaml
drwxr-xr-x    9 root     root          4096 Jul  3 18:21 custom_components
drwxr-xr-x    2 root     root          4096 Jan 12 17:15 deps
-rw-r--r--    1 root     root           152 Feb 15 17:48 groups.yaml
-rwxr--r--    1 root     root           993 Mar 31 18:43 hall - Copy.yaml
-rw-r--r--    1 root     root          1090 Jun 28 16:15 hall.yaml
-rw-r--r--    1 root     root          9047 Jul 13 16:52 home-assistant.log
-rw-r--r--    1 root     root     529719296 Jul 13 17:12 home-assistant_v2.db
-rw-r--r--    1 root     root         32768 Jul 13 17:12 home-assistant_v2.db-shm
-rw-r--r--    1 root     root         24752 Jul 13 17:12 home-assistant_v2.db-wal
-rw-r--r--    1 root     root           997 Mar 31 18:43 hot_water.yaml
drwxr-xr-x    4 root     root          4096 Jan 16 10:15 image
-rw-r--r--    1 root     root           999 Mar 31 18:43 kitchen.yaml
-rw-r--r--    1 root     root           192 Feb  2 08:09 known_devices.yaml
-rw-r--r--    1 root     root           997 Mar 31 18:43 lounge.yaml
drwxr-xr-x    3 root     root          4096 Feb 24 16:39 netdaemon
-rw-r--r--    1 root     root          1003 Mar 31 18:43 pink.yaml
-rw-r--r--    1 root     root             0 Jan 12 17:15 scenes.yaml
-rw-r--r--    1 root     root          1237 Mar  1 11:16 schedule_study.yaml
-rwxr--r--    1 root     root          3418 Mar 28 15:21 scripts - Copy.yaml
-rw-r--r--    1 root     root          5543 Jul 13 09:25 scripts.yaml
-rw-r--r--    1 root     root           161 Jan 12 17:15 secrets.yaml
drwxr-xr-x    2 root     root          4096 Jul 13 17:02 shell
-rw-r--r--    1 root     root          1212 Jun 28 16:12 study.yaml
drwxr-xr-x    2 root     root          4096 Jan 13 22:01 tts
drwxr-xr-x    3 root     root          4096 Jan 27 12:46 www
-rwxr--r--    1 root     root             2 Jul 13 15:36 yellow.yaml
-rw-r--r--    1 root     root         86016 Mar  8 16:26 zigbee.db
drwxr-xr-x    3 root     root          4096 Jul 13 16:39 zigbee2mqtt
drwxr-xr-x    3 root     root          4096 Mar 12 18:11 zigbee2mqtt-temp
drwxr-xr-x    3 root     root          4096 Mar  8 15:25 zigbee2mqttold
➜  config cat shell/script.sh
#!/bin/bash
echo "Hello World"
rm config/blue.yaml
rm config/conservatory.yaml
rm config/hall.yaml
rm config/kitchen.yaml
rm config/lounge.yaml
rm config/pink.yaml
rm config/study.yaml
rm config/yellow.yaml
read -p "Done removing. "
cp "/config/Wiser_Schedule_Backup/blue - Copy.yaml" /config/blue.yaml
cp "/config/Wiser_Schedule_Backup/conservatory - Copy.yaml" /config/conservatory.yaml
cp "/config/Wiser_Schedule_Backup/hall - Copy.yaml" /config/hall.yaml
cp "/config/Wiser_Schedule_Backup/kitchen - Copy.yaml" /config/kitchen.yaml
cp "/config/Wiser_Schedule_Backup/lounge - Copy.yaml" /config/lounge.yaml
cp "/config/Wiser_Schedule_Backup/pink - Copy.yaml" /config/pink.yaml
cp "/config/Wiser_Schedule_Backup/study - Copy.yaml" /config/study.yaml
cp "/config/Wiser_Schedule_Backup/yellow - Copy.yaml" /config/yellow.yaml
➜  config bash shell/script.sh
Hello World
': No such file or directorye.yaml
': No such file or directoryservatory.yaml
': No such file or directoryl.yaml
': No such file or directorychen.yaml
': No such file or directorynge.yaml
': No such file or directoryk.yaml
': No such file or directorydy.yaml
': No such file or directorylow.yaml
^Cne removing.
➜  config ls -la
total 517688
drwxr-xr-x   17 root     root          4096 Jul 13 17:12 .
drwxr-xr-x    1 root     root          4096 Jul  3 18:35 ..
-rw-r--r--    1 root     root             8 Mar  9 12:42 .HA_VERSION
drwxr-xr-x    2 root     root          4096 Jan 12 17:15 .cloud
-rw-r--r--    1 root     root          1550 Jul 13 12:55 .sonoff.json
drwxr-xr-x    3 root     root          4096 Jul 13 17:11 .storage
drwxr-xr-x    2 root     root          4096 Jun 28 17:47 Temp
drwxr-xr-x    2 root     root          4096 Jul 13 09:21 Wiser_Schedule_Backup
-rwxr--r--    1 root     root          7165 Feb 28 18:41 automations - Copy.yaml
-rw-r--r--    1 root     root         35958 Jul 13 13:38 automations.yaml
-rwxr--r--    1 root     root             2 Jul 13 13:56 blue.yaml
drwxr-xr-x    3 root     root          4096 Jan 12 17:15 blueprints
-rw-r--r--    1 root     root          8693 Jul 13 14:10 configuration.yaml
-rwxr--r--    1 root     root             2 Jul 13 13:48 conservatory.yaml
drwxr-xr-x    9 root     root          4096 Jul  3 18:21 custom_components
drwxr-xr-x    2 root     root          4096 Jan 12 17:15 deps
-rw-r--r--    1 root     root           152 Feb 15 17:48 groups.yaml
-rwxr--r--    1 root     root           993 Mar 31 18:43 hall - Copy.yaml
-rw-r--r--    1 root     root          1090 Jun 28 16:15 hall.yaml
-rw-r--r--    1 root     root          9047 Jul 13 16:52 home-assistant.log
-rw-r--r--    1 root     root     529719296 Jul 13 17:12 home-assistant_v2.db
-rw-r--r--    1 root     root         32768 Jul 13 17:12 home-assistant_v2.db-shm
-rw-r--r--    1 root     root         45352 Jul 13 17:12 home-assistant_v2.db-wal
-rw-r--r--    1 root     root           997 Mar 31 18:43 hot_water.yaml
drwxr-xr-x    4 root     root          4096 Jan 16 10:15 image
-rw-r--r--    1 root     root           999 Mar 31 18:43 kitchen.yaml
-rw-r--r--    1 root     root           192 Feb  2 08:09 known_devices.yaml
-rw-r--r--    1 root     root           997 Mar 31 18:43 lounge.yaml
drwxr-xr-x    3 root     root          4096 Feb 24 16:39 netdaemon
-rw-r--r--    1 root     root          1003 Mar 31 18:43 pink.yaml
-rw-r--r--    1 root     root             0 Jan 12 17:15 scenes.yaml
-rw-r--r--    1 root     root          1237 Mar  1 11:16 schedule_study.yaml
-rwxr--r--    1 root     root          3418 Mar 28 15:21 scripts - Copy.yaml
-rw-r--r--    1 root     root          5543 Jul 13 09:25 scripts.yaml
-rw-r--r--    1 root     root           161 Jan 12 17:15 secrets.yaml
drwxr-xr-x    2 root     root          4096 Jul 13 17:02 shell
-rw-r--r--    1 root     root          1212 Jun 28 16:12 study.yaml
drwxr-xr-x    2 root     root          4096 Jan 13 22:01 tts
drwxr-xr-x    3 root     root          4096 Jan 27 12:46 www
-rwxr--r--    1 root     root             2 Jul 13 15:36 yellow.yaml
-rw-r--r--    1 root     root         86016 Mar  8 16:26 zigbee.db
drwxr-xr-x    3 root     root          4096 Jul 13 16:39 zigbee2mqtt
drwxr-xr-x    3 root     root          4096 Mar 12 18:11 zigbee2mqtt-temp
drwxr-xr-x    3 root     root          4096 Mar  8 15:25 zigbee2mqttold
➜  config

What am I trying to do??

Well back to basics - in home assistant I want to delete some yaml files in my config directory and replace them with a replacement file

So I have in configuration.yaml

shell_command:
  my_script: bash /config/shell/script.sh

then I my script.yaml I have

run_my_script:
  alias: Run my_script
  sequence:
  - service: shell_command.my_script
  mode: single

and then the contents of /config/shell/script.sh

#!/bin/bash
echo "Hello World"
rm config/blue.yaml
rm config/conservatory.yaml
rm config/hall.yaml
rm config/kitchen.yaml
rm config/lounge.yaml
rm config/pink.yaml
rm config/study.yaml
rm config/yellow.yaml
read -p "Done removing. "
cp "/config/Wiser_Schedule_Backup/blue - Copy.yaml" /config/blue.yaml
cp "/config/Wiser_Schedule_Backup/conservatory - Copy.yaml" /config/conservatory.yaml
cp "/config/Wiser_Schedule_Backup/hall - Copy.yaml" /config/hall.yaml
cp "/config/Wiser_Schedule_Backup/kitchen - Copy.yaml" /config/kitchen.yaml
cp "/config/Wiser_Schedule_Backup/lounge - Copy.yaml" /config/lounge.yaml
cp "/config/Wiser_Schedule_Backup/pink - Copy.yaml" /config/pink.yaml
cp "/config/Wiser_Schedule_Backup/study - Copy.yaml" /config/study.yaml
cp "/config/Wiser_Schedule_Backup/yellow - Copy.yaml" /config/yellow.yaml

I got to my original question by trying to work out why it wasnt working so broke it down into parts to see where the error was coming from.

lcsneil

You are assumingcp rm are in the script’s path

The rm did not delete anything because there is no file named config/blue.yaml in your working directory; there is blue.yaml (full path /root/config/blue.yaml).
You seem to be in /root/config/, but then copy files to /config/. Which of these is the correct path?
I would avoid messing with relative paths and specify an absolute path to every file you are trying to remove – that would be either rm /config/blue.yaml or rm /root/config/blue.yaml, depending on which of the directories contains the files you are trying to remove.

Are you sure replacing configuration files is the best way to achieve what you are ultimately trying to do?

BTW to replace a file, you don’t need to delete it first. cp should replace it automatically if you don’t give it any flags (such as -i).

The script does not work even when run manually, so I think we should solve that first.
If it was working, the next step would indeed be to run the following commands and specify the full path to cp and rm.

which cp
which rm

The environment of the script is different than the user one, usually.

I know, but when we start the script manually from a shell, the script inherits the shell’s environment. And it still does not work properly. We did not get to starting the script from HA yet. If we were having issues with PATH at this point, we would be seeing “command not found” errors.

The first line of the script triggers a new shell. Yes, I am a certified UNIX administrator

It is all path related…

If at the command line I type rm blue.yaml then it deletes blue.yaml
however in the .sh file it needs to be the full path so the correct script.sh is

#!/bin/bash
echo "Hello World"
rm /root/config/blue.yaml
rm /root/config/conservatory.yaml
rm /root/config/hall.yaml
rm /root/config/kitchen.yaml
rm /root/config/lounge.yaml
rm /root/config/pink.yaml
rm /root/config/study.yaml
rm /root/config/yellow.yaml
read -p "Done removing. "
cp "/root/config/Wiser_Schedule_Backup/blue - Copy.yaml" /root/config/blue.yaml
cp "/root/config/Wiser_Schedule_Backup/conservatory - Copy.yaml" /root/config/conservatory.yaml
cp "/root/config/Wiser_Schedule_Backup/hall - Copy.yaml" /root/config/hall.yaml
cp "/root/config/Wiser_Schedule_Backup/kitchen - Copy.yaml" /root/config/kitchen.yaml
cp "/root/config/Wiser_Schedule_Backup/lounge - Copy.yaml" /root/config/lounge.yaml
cp "/root/config/Wiser_Schedule_Backup/pink - Copy.yaml" /root/config/pink.yaml
cp "/root/config/Wiser_Schedule_Backup/study - Copy.yaml" /root/config/study.yaml
cp "/root/config/Wiser_Schedule_Backup/yellow - Copy.yaml" /root/config/yellow.yaml

So I now have to get this working as a script.

I have renamed the script to Wiserreset.sh and put it back in the shell subdirectory and also added the -f (force command to the rm and cp commands.

So a typical line now looks like
rm -f /root/config/blue.yaml
cp -f “/root/config/Wiser_Schedule_Backup/blue - Copy.yaml” /root/config/blue.yaml

However when I fire the script it doesnt work and gives the error

Logger: homeassistant.components.shell_command
Source: /usr/src/homeassistant/homeassistant/components/shell_command/__init__.py:113
Integration: Shell Command (documentation, issues)
First occurred: 18:57:41 (1 occurrences)
Last logged: 18:57:41

Error running command: `bash /root/config/shell/Wiserreset.sh`, return code: 127
NoneType: None

From my configuration.yaml

shell_command:
  my_script: bash /root/config/shell/Wiserreset.sh

HOWEVER if in the configuration.yaml I change the script to “bash shell/Wiserreset.sh” I get a return code of 1 rather than 127

Logger: homeassistant.components.shell_command
Source: /usr/src/homeassistant/homeassistant/components/shell_command/__init__.py:113
Integration: Shell Command (documentation, issues)
First occurred: 18:49:38 (2 occurrences)
Last logged: 18:52:24

Error running command: `bash shell/Wiserreset.sh`, return code: 1
NoneType: None

Any ideas how to get it to run under a script?

(Thanks for the help so far… definitely moving forward)

lcsneil

Now would be the time to run which cp and which rm and put the full paths to the commands to your script (e.g. /usr/bin/rm /root/config/blue.yaml).

Keep bash /root/config/shell/Wiserreset.sh if that is where you put the script. I would try to avoid relative paths as much as possible.

Just to make sure, when you now start the script manually, it works, right?

Yes, and the new shell should inherit the PATH that was exported in the shell that invoked it.

$ ed     
a
#!/bin/sh
echo $test
.
w test
21
q
$ chmod +x test
$ ./test                                                       

$ export test="ABC" 
$ ./test           
ABC
$ 

As long as the script was being executed from a login shell, it had the correct PATH.

Now, when the script is supposedly working fine when started manually in any working directory, but does not work when HA starts it, I am suspecting PATH could be the issue. Even more so because we cannot see the error messages and are getting return code 127, which is what bash exits with when it cannot find a command.

Yes the line

/bin/bash /root/config/shell/Wiserreset.sh

works fine when running manually in a putty session.

➜  config which bash
/bin/bash
➜  config which rm
/bin/rm
➜  config which cp
/bin/cp
➜  config

the shell script is now

#!/bin/bash
/bin/rm -f /root/config/blue.yaml
/bin/rm -f /root/config/conservatory.yaml
/bin/cp -f "/root/config/Wiser_Schedule_Backup/blue - Copy.yaml" /root/config/blue.yaml
/bin/cp -f "/root/config/Wiser_Schedule_Backup/conservatory - Copy.yaml" /root/config/conservatory.yaml

configuration.yaml is

shell_command:
  my_script: /bin/bash /root/config/shell/Wiserreset.sh

script.yaml is

run_my_script:
  alias: Run my_script
  sequence:
  - service: shell_command.my_script
  mode: single

Check configuration and restart the server just to be sure

When I run the script I still get

Logger: homeassistant.components.shell_command
Source: /usr/src/homeassistant/homeassistant/components/shell_command/__init__.py:113
Integration: Shell Command (documentation, issues)
First occurred: 7:55:23 (1 occurrences)
Last logged: 7:55:23

Error running command: `/bin/bash /root/config/shell/Wiserreset.sh`, return code: 127
NoneType: None

One question should the first line of the shell script be
#!/bin/bash
or
#!/bin/sh

lcsneil