-2

I've written a script to reboot my router every other day. It works as intended when I test it out manually but doesn't work properly in cron.

#!/bin/bash

c=$(ls -a /tmp | grep -o ".daycount*" | wc -l)

if [ "$c" -lt 2 ]; then
  let c="$c"+1
  touch /tmp/.daycount"$c"
  exit

else
  rm /tmp/.daycount*
  sshpass -f /home/username/.sshpasswrd ssh [email protected] reboot
  exit
fi

When grep find no files called .daycount* it creates one called .daycount1

Everyday it would increment by 1 until it hits the "-lt #" threshold, where it would delete all the .daycount* and then reboot my router. In this case, every three days.

It works as intended when I run it manually, but when I run it in cron, it does all the creating/deleting of the files but won't reboot my router.

I've tested it many days in a row and when I check the uptime of the router it has not reset to zero when I would expect it to.

10
  • 6
    This script has many many problems (mostly spaces where they shouldn't be, or missing where they're required, but also let isn't a shell command, and...), so the question isn't why it doesn't work from cron, the question is how it manages to work manually. shellcheck.net will point out some (but not all) of the problems. BTW, does Asuswrt-Merlin even include bash, or just some more basic shell? Commented Sep 27 at 18:16
  • 2
    @GordonDavisson let is a bash command, where each argument is executed as arithmetic expression. Here it is used with wring syntax. Commented Sep 27 at 19:08
  • It's worth noting that rm /tmp/.daycount * will delete both /tmp/.daycount and all files in the current directory that don't start with .. You should double-check that this is what you intend to do. Commented Sep 27 at 19:44
  • "I've written a script to reboot my router every other day." Does this script run on the router, or does the script simply ssh to the router to run reboot? It's important that you clarify this, because AsusWRT ships a lot of strange shell utilities that act slightly different from more commonly seen counterparts on other distros. Commented Sep 27 at 19:46
  • 2
    Put set -x at the beginning of the script, and redirect stderr to a file. Then you'll see a trace of the script's execution and its errors in the file, which should help debug it. Commented Sep 27 at 21:38

1 Answer 1

0

The difference may have to do with having an interactive session. When you run ssh in an interactive shell, you'll be connected to a TTY, but automated scripts run by cron will not. Moreover, Bash will read from ~/.bash_profile on an interactive shell and ~/.bashrc for a non-interactive one, which can lead to subtle differences in the environment.

You might try debugging ssh by adding the -vvv option and capturing the output and see what's different between the manual and cron runs. Another thing to try would be the -t option for ssh.

Other Suggestions

Truly learning a command language interpreter, especially one with as large of a manual as Bash has, can take years. In the hopes of accelerating that, I thought I'd share these suggestions unrelated to your query:

  • Your grep argument looks like a glob, but grep uses regex and yours will match files that have daycount anywhere in the name (though there must be one character before). You probably want grep '^\.daycount.*' (though the .* is actually unnecessary); see regex101.com for details on how these differ.

    But you don't actually need grep: c=$(ls -1d /tmp/.daycount* | wc -l) will do. This uses globs to select the files. The -d option ensures directories matching this pattern are only one line; the -1 is implied, but I make it explicit here.

  • Using rm /tmp/.daycount[0-9] further limits how many files might be deleted to just those 10 possible files: /tmp/.daycount0 through /tmp/.daycount9.

  • You can omit both exit commands, as there is an implicit exit at the end of every script.

  • It's considered safer to use SSH keys rather than passwords when practical, and they come in handy when running automated scripts as no password is required. You can set one up by doing the following (only needs to be done once):

    ssh-keygen -N ''               # Create the key
    ssh-copy-id [email protected]   # Authorize (install) the key
    

    Then you can do ssh [email protected] reboot without ever being asked for a password.

  • Is it possible to configure cron on 192.168.0.1? If so, you can completely avoid the SSH step that is causing problems by having the script run locally.

  • Note: You can escape characters like " and \ in a "" string (e.g. "\" \\"), but you cannot escape anything in a '' string, not even ' – any \ gets passed unmodified. A$'' string (a.k.a. ANSI-C Quoting) does allow escapes; it's complicated.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.