0

I have written a small code snippet to check the aws cli version

#!/bin/bash
if [ -e "/usr/local/bin/aws" ];
then
    myAWS="/usr/local/bin/aws"
else
    myAWS="/usr/bin/aws"
fi

myCmd=("${myAWS} --version")

echo "$myCmd"

message=$($myCmd)

echo "$message"

Now while running this manually with root user I am able to run but after our aws cli upgrade while running this via crontab

57 21 * * * /rough/scripts/log/test.sh > /rough/scripts/log/test.log 2>&1 

I face the below error , can you suggest , i have reinstalled the aws cli but to no effect.

/usr/local/bin/aws --version
Traceback (most recent call last):
  File "aws", line 19, in <module>
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "PyInstaller/loader/pyimod02_importers.py", line 493, in exec_module
  File "awscli/clidriver.py", line 43, in <module>
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "PyInstaller/loader/pyimod02_importers.py", line 493, in exec_module
  File "awscli/help.py", line 20, in <module>
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "PyInstaller/loader/pyimod02_importers.py", line 493, in exec_module
  File "docutils/core.py", line 23, in <module>
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "PyInstaller/loader/pyimod02_importers.py", line 493, in exec_module
  File "docutils/io.py", line 43, in <module>
UnicodeEncodeError: 'utf-8' codec can't encode characters in position 4-6: surrogates not allowed
[24036] Failed to execute script 'aws' due to unhandled exception!
steeldriver
  • 136,215
  • 21
  • 243
  • 336
  • cron runtime environment is different. see https://unix.stackexchange.com/questions/673908/why-crontab-doesnt-execute-a-scheduled-bash-script/673918#673918 – waltinator Mar 11 '23 at 00:51
  • Thanks @waltinator, is there a way I can check the current crontab runtime enviroment ? – AashkaTe Mar 11 '23 at 05:22
  • Is it possible that an aws configuration file in your profile (~/.aws/config, ~/.aws/credentials etc.) has a non UTF-8 encoding and your local environment handles that by setting PYTHONIOENCODING for example? – steeldriver Mar 11 '23 at 13:49
  • hi @steeldriver- I checked the ./aws/config file ----cat ~/.aws/config [default] s3 = signature_version = s3v4 region=eu-west-1 I am confused that if i run the script manually it runs fine but crontab is giving me the problem, any suggestions that can help surpass this error – AashkaTe Mar 11 '23 at 14:06
  • May I ask what the point of the script is? I mean, why bother having the if to check two directories that are already in your $PATH? The whole script looks like it can be simplified to just the single command aws --version. Is it that you want to always prioritize the version found in /usr/local/bin/ even if there is another in /usr/bin/? And why do message=$(command); echo $message instead of simply just running command directly? – terdon Mar 11 '23 at 14:44

1 Answers1

0

Cron has its own PATH which is hardcoded in the source code. This means that cron commands will run in a different environment. My guess is that your user (or root) are configured with a different python in their PATH. Or maybe you activate a python environment on login, or have installed some pip packages. Whatever the case may be, you will need to reproduce that in your cron.

First, run echo "$PATH" while logged in as the user for whom the command works. Then, take the PATH that prints and add it to the beginning of the crontab:

PATH="blah;blah;blah"
57 21 * * * /rough/scripts/log/test.sh > /rough/scripts/log/test.log 2>&1 

If that doesn't work, you can try loading the user's shell configuration file with bash -i:

       -i        If the -i option is present, the shell is interactive.

That will force bash to run in "interactive" mode, meaning it will read the invoking user's ~/.bashrc file (see https://askubuntu.com/a/438170/85695):

57 21 * * * bash -i /rough/scripts/log/test.sh > /rough/scripts/log/test.log 2>&1 

If that still doesn't work, you will need to figure out exactly what python setup you are using and where it comes from and try to reproduce that in the crontab. If you edit your question with more detail about your setup we might be able to help.


On an unrelated note, you could simplify your script a little. First, since both /usr/local/bin and /usr/bin are in the default PATH, if the objective of your if is to find which of the two contains an aws executable, then you don't need the if at all and can simply run aws.

If instead you want to always prioritize the version in /usr/local/bin even if there is another one in /usr/bin, then the if makes sense.

Next, there's not much point in running message=$(command); echo $message: if command prints out what you want to see, just run it directly. I would write your script like this instead:

#!/bin/bash
myAws=/usr/bin/aws
[ -e /usr/local/bin/aws ] && myAws=/usr/local/bin/aws

myCmd=("$myAWS" "--version") echo "${myCmd[@]}" "${myCmd[@]}"

Or, if you just want to run an aws and the if was only to figure out where it is installed, and you also want to see the full path to it, simply:

#!/bin/bash
myAws=$(which aws)
myCmd=("$myAws" "--version")
echo "${myCmd[@]}"
"${myCmd[@]}"
terdon
  • 100,812