# svn+ssh + crontab + ssh-agent

## eleanor

Hi, I have the following problem: my script works if run as root from the console (as root), but doesn't work if dcron executes it, and I don't know why, since in both cases it's run as root.

I have set up:

1) the script:

```

#!/bin/bash

USER=eleanor

HOST=<host>

TESTCASES_DIR=/Testcases/

LOG_FILE=/var/log/logs

# redirect stdout to a file

exec 1>>"$LOG_FILE"

echo "******************** TESTCASES *********************"

# changes (changed + added)

LINES=$(svn status $TESTCASES_DIR | wc -l)

if [ $LINES -gt 0 ]

then

  cd $TESTCASES_DIR

  svn update

  echo "Adding files: $TESTCASES_DIR"

  ADD_FILES=$(svn status | grep '^?' | awk '{print $2}' | wc -l)

  if [ $ADD_FILES -gt 0 ]

  then

    svn add $(svn status | grep '^?' | awk '{print $2}')

  fi

  svn commit --message "Adding from $TESTCASES_DIR on: $(date)"

fi

```

so the script works if run as root+eleanor, but not in cron.

This is in crontab:

```
27 * * * * bash /scripts/svn.sh
```

This are additional settings:

- the server only accepts certificate from the eleanor user

- the ssh-agent is running all the time (so I don't have to type a password for certificate all the time)

- the /root/.ssh/config contains:

```

Host <host>

    User eleanor

```

so the ssh parameters are changes upon ssh connection (and if root user is connecting to the host, it's connecting as eleanor - the allowed user), so this is no problem.

The problem is the cron deamon or something (and it is run surely, because I've done my logging and they say):

 *Quote:*   

> 
> 
> Sun Oct 11 14:24:01 CEST 2009
> 
> SVN:
> ...

 

but there are files to update (surely), and I don't know why it doesn't work.

Any ideas anyone?

----------

## nlopez

This is probably an environment issue. Try changing your crontab line to

```
27 * * * * bash -li -c '/scripts/svn.sh'
```

This will ensure that bash loads up your .bash_profile as if it were an interactive shell.

To see the difference between cron's environment and your interactive shell, you can do

```
env > /tmp/myenv
```

and schedule a cronjob for

```
* * * * * env > /tmp/cronenv.bare

* * * * * bash -li -c 'env > /tmp/cronenv.good'
```

myenv and cronenv.good should be identical, while cronenv.bare will often not contain the variables you'd like your scripts to have when you're trying to do your ssh backups (namely SSH_AGENT).Last edited by nlopez on Sun Oct 11, 2009 5:19 pm; edited 1 time in total

----------

## Hu

 *eleanor wrote:*   

> 
> 
> ```
>   ADD_FILES=$(svn status | grep '^?' | awk '{print $2}' | wc -l)
> ```
> ...

 

You should add a  || exit 1 to the initial cd, so that failure to cd does not result in running the commands in the wrong directory -- and with full root privilege!

This could be simplified by replacing the grep+awk pair with awk '/^?/ { print $2; }'.

You should probably run the svn add with --non-interactive, just to discourage it from asking any questions.

Your svn add will likely mishandle targets with spaces in their name.  You might be able to get around this by directing the output to a file, then using the --targets option, but I have not tried this.

As an extension to nlopez's remarks on environment: is $SVN_SSH set the same way in both contexts?  How do you expect the script to find the ssh-agent?  It is normally found via environment variables, but your script does not set any such variables.

----------

## eleanor

Here are the corresponding environments:

 *Quote:*   

> eleanor-laptop scripts # cat /tmp/env.base
> 
> SHELL=/bin/sh
> 
> TERM=rxvt
> ...

 

So, the *SSH* environments are not set. What can I do?

And I guess the SSH agent is found via this two variables:

 *Quote:*   

> 
> 
> eleanor-laptop scripts # env | grep SSH
> 
> SSH_AGENT_PID=6025
> ...

 

Any ideas on how to solve it?Last edited by eleanor on Sun Oct 11, 2009 8:39 pm; edited 1 time in total

----------

## nlopez

 *eleanor wrote:*   

> Any ideas on how to solve it?

 

I accomplish this using keychain and a line in my .bash_profile similar to

```
eval `keychain --eval --quiet --quick ~/.ssh/id_rsa`
```

----------

## eleanor

I already have this:

```

#!/usr/bin/expect -f

set timeout 20

# connect to the remote server

spawn keychain --eval /home/eleanor/.ssh/id_dsa

# supply the keychain password

expect "id_dsa: $"

send "<password>\r"

interact

```

so this is not a problem. A problem must be somewhere else. Any other ideas?

----------

## nlopez

With keychain in your bash_profile and the crontab line I provided it shouldn't be necessary to have Expect input your private key password (password-less authentication for scripts via private key is a use case keychain is specifically designed for.) 

Once you've unlocked your private key once with keychain on the server executing this script, the bash_profile line will ensure that scripts run via bash -li -c '/path/to/script.sh' are aware of the ssh-agent that's holding your decrypted private key.

 Once the eval keychain line is in your bash profile you should see SSH_AGENT show up in that /tmp/cronenv.good file.

----------

## eleanor

Ah, this article helped me a lot: http://linuxshellaccount.blogspot.com/2007/10/crontab-and-your-environment.html

Well, I had to source the environment variables into the cron environment, now it works fine.

Thanks for all your help

----------

