Shell script does not work if I put it in crontab, if I put it crontab I must to use sudo for working crontab

I use latest Manjaro, and I use this script for test SSH connection quality.

#!/bin/bash
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
PATH=/bin:/usr/bin:/sbin
# Define the remote servers and output files
servers=( "1.2.3.4" "1.2.3.5" )
output_files=( "server1_output.txt" "server2_output.txt" )

# Define the user to connect as
user="admin"

# Loop over the servers
for i in "${!servers[@]}"
do
  server="${servers[$i]}"
  output_file="${output_files[$i]}"

  # Test the SSH connection quality
  ssh_start_time=$(date +%s.%N)
  ssh_quality=$(ssh -q -o BatchMode=yes -o ConnectTimeout=5 "$user@$server" "echo SSH quality test successful." 2>&1)
  ssh_end_time=$(date +%s.%N)
  ssh_time=$(echo "$ssh_end_time - $ssh_start_time" | bc)

  # Check the SSH connection quality
  if echo "$ssh_quality" | grep -q "successful"; then
    echo "SSH quality to $server is good. SSH time: $ssh_time seconds." >> "$output_file"
    
    # Run the ls command and write output to file
    ssh -q "$user@$server" "ls -la" >> "$output_file"
  else
    echo "SSH quality to $server is poor." >> "$output_file"
  fi

  # Close the SSH connection
  ssh -q -O exit "$user@$server"
done

If run this shell script it work without problem and put result in files, this script check SSH connection quality and run

ls -la

command on the servers and put result in files.
I want crontab run this shell script every hour and put result in files. so I type this command

crontab -e

I normal user without sudo command.
I also install cronie by pacman and it is running

 sudo systemctl status cronie.service                                                                                                                                                       ✔ 
â—Ź cronie.service - Periodic Command Scheduler
     Loaded: loaded (/usr/lib/systemd/system/cronie.service; enabled; preset: disabled)
     Active: active (running) since Tue 2023-05-02 15:04:00 +0330; 22h ago
   Main PID: 114364 (crond)
      Tasks: 1 (limit: 28660)
     Memory: 1.2M
        CPU: 1min 1.948s
     CGroup: /system.slice/cronie.service
             └─114364 /usr/bin/crond -n

Mai 03 13:34:01 faridi CROND[183386]: (mostafa) CMDOUT (/bin/sh: line 1: /sh: No such file or directory)
Mai 03 13:34:01 faridi CROND[183386]: (mostafa) CMDEND (/sh  /home/mostafa/ssh-test/ssh-test3.sh)
Mai 03 13:34:01 faridi CROND[183387]: (mostafa) CMDEND (mostafa /sh  /home/mostafa/ssh-test/ssh-test2.sh >> /home/mostafa/ssh-test/ssh-test.log)
Mai 03 13:34:01 faridi CROND[183386]: pam_unix(crond:session): session closed for user mostafa
Mai 03 13:34:01 faridi CROND[183387]: pam_unix(crond:session): session closed for user mostafa
Mai 03 13:35:01 faridi crond[183484]: pam_unix(crond:session): session opened for user mostafa(uid=1000) by (uid=0)
Mai 03 13:35:01 faridi CROND[183485]: (mostafa) CMD (mostafa /sh  /home/mostafa/ssh-test/ssh-test2.sh >> /home/mostafa/ssh-test/ssh-test.log)
Mai 03 13:35:01 faridi CROND[183484]: (mostafa) CMDOUT (/bin/sh: line 1: mostafa: command not found)
Mai 03 13:35:01 faridi CROND[183484]: (mostafa) CMDEND (mostafa /sh  /home/mostafa/ssh-test/ssh-test2.sh >> /home/mostafa/ssh-test/ssh-test.log)
Mai 03 13:35:01 faridi CROND[183484]: pam_unix(crond:session): session closed for user mostafa

but this crontab is not working and I do not see any result.

when I run this command

crontab -e

by sudo

sudo crontab -e

it works, but result are different and I see only message like this

SSH quality to 1.2.3.4 is poor

and I do not see more detail.
but when I run this script manually without crontab I see these

-rw-rw-r--   1 admin admin      246 Nov  8 11:19 .yarnrc
SSH quality to 1.2.3.4 is good. SSH time: 10.837039616 seconds.
total 38704
drwx------. 31 admin admin     4096 May  3 09:52 .
drwxr-xr-x.  5 root  root        52 Dec 11 15:24 ..
drwxr-xr-x   8 admin admin      156 May  8  2022 dffdsfds_mock
-rw-------.  1 admin admin    23734 May  2 13:28 .bash_history
-rw-r--r--.  1 admin admin       18 Mar 12  2019 .bash_logout
-rw-r--r--.  1 admin admin      193 Mar 12  2019 .bash_profile
-rw-r--r--   1 admin admin      531 Apr  5 14:11 .bashrc
drwxrwxr-x.  6 admin admin       57 Nov  8 09:45 .cache

this is my crontab

*/1 * * * *  mostafa /sh  /home/mostafa/ssh-test/ssh-test2.sh

I do not know why this is happen

I don’t use cron - but a systemd timer - this can be done as --user so you don’t need root.

You can find an implementation you can learn from in this topic

I know you asked specifically about cron - but I have never used so …

Telling how to solve the problem using different tool is not a solution, especially when the issue is with a tool officially supported.

i would think it has to do with cron running the script as other user/different env. compared to your user.

A quick google can give you hints how to set up cron running it as your user which you found to be working. From what i understand, by default cron runs as root and you need to specify more if you want it run as user.

Manjaro doesn’t encourage the use of cron but the use of systemd timers.

A timer activates a service definition on a schedule.

The service definition and timer definition mandates same name but different extension

~/.config/systemd/user/ssh-test.service

[Unit]
Description=Run ssh connection test
# wait for network
After=syslog.target network.target default.target

[Service]
Type=simple
ExecStartPre=/bin/sleep 30
ExecStart=/home/%u/ssh-test/ssh-test2.sh

[Install]
WantedBy=default.target

~/.config/systemd/user/ssh-test.timer

[Unit]
Description=Schedule ssh test

[Timer]
OnBootSec=10m
Persistent=true
OnCalendar=0/1:00:00
OnUnitActiveSec=1h

[Install]
WantedBy=timers.target

Enable and start only the timer as the timer will activate the service which runs the script

systemctl --user enable ssh-test.timer
systemctl --user start ssh-test.timer

A point to consider in your script is your output files. Depending on the path from where the script is run the files will be created in arbitrary locations.

So defining your output files with a full path will ensure they are always created/modified in the same location

[...]
output_files=( "$HOME/server1_output.txt" "$HOME/server2_output.txt" )
[...]
2 Likes

Thanks nice guide,
but when I run this command

vim ~/.config/systemd/user/ssh-test.service

and put your guide and press :wq
I see this error

~/.config/systemd/user/ssh-test.service" E212: Can't open file for writing

and can not write to file
I run that command by sudo too and I see that error again
I think we must put this service to another path

don’t use sudo for anything inside your home - did you create the folder beforehand?

systemd service units mandates the mentioned path

1 Like

I recommend following what linux-aarhus says, but some insight on CRON, I recently needed to add a CRON job for a script and also ran into this kind of issues when adding my user CRON job. for example some environment variables needed to be added, the comands needed to be prefix with more environment variables, because YES, cron is not running as your user inside your current user desktop environment, it runs as your user (that is if you create USER cronjobs with crontab -e and not sudo crontab of course), but in a very limited environment. On my side I went with trial and error and eventually reached my goal, but yeah you can’t copy paste a user script working on your desktop environment directly into CRON, some steps need to be added. This is expected. in my specific case the CRON job itself needed this environment variable to be set for the script desktop notification to land on my desktop:

# crontab job every 10 minutes
*/10 * * * * XDG_RUNTIME_DIR=/run/user/$(id -u) /home/omano/Scripts/plasmashellMonitor.sh

and in my script I needed to specify things like the DISPLAY for example for inxi comand or else it does not have a DISPLAY in the CRON environment and can’t get some information:

DISPLAY=:0 inxi -aG -c

As said, trial and error, tests, tests, tests, and you can figure it out.

But yeah, do the simple methods explained to you above.

1 Like

Your else clause is in effect because when you run as root - there is no access to ssh agent or ssh config thus your script will fail the connection because credentials are missing.

1 Like

How can solve this problem?
Do I need make ssh key for root user ? and this script give me more detail?

Thanks your guide solve my problem.
it work like charm

Thanks
nice guide,
but I do not understand,
do I have to disable user.servcei and run timer.service.
or first we disable user.service and after enable timer.service, start it again ?

Hi
Can you try sudo crontab -e ?

The permissions of this file must be 0644

Luck

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.