1

I need save mysql dump from remote machine to file on local, so connect via ssh to remote machine, run mysqldump on remote machine and save it to file on local, where script is running.

I have 2 bash scripts, function.sh and export-db.sh, and 1 configuration file export-db-ssc.cfg

File function.sh.

#!/bin/bash

cd "$(dirname "${BASH_SOURCE[0]}")"

date_time="$(date "+%Y%m%d-%H%M%S")"
date_time_now="date +%Y%m%d-%H%M%S"
file_name="$(basename "$0")"
file_log="log/${file_name%.*}.log"
email_sender='[email protected]'
email_recipients='[email protected]'

message()
{
    if [ $1 = "i" ]
    then
        echo "`$date_time_now`|sofimon|"$file_name"|$2|info." 2>&1 | tee -a "$file_log"
    elif [ $1 = "t" ]
    then
        echo "`$date_time_now`|sofimon|"$file_name"|$2|true." 2>&1 | tee -a "$file_log"
    else [ $1 = "f" ]
        echo "`$date_time_now`|sofimon|"$file_name"|$2|false!" 2>&1 | tee -a "$file_log"
    fi
}

# $1 = description, $2 = command, $3 = command if $2 is true, $4 = command if $2 is false
doit()
{
    if
        $2
    then
        message "t" "$1"
        "$3"
    else
        message "f" "$1"
        result="false"
        "$4"
    fi
}

email()
{
cat "$file_log" | mail -a "From: sofimon <$email_sender>" -a "Content-type: text/plain" -s "sofimon" -r $email_sender $email_recipients
mv "$file_log" "$file_log"-"$date_time"
rm -rf "$file_log"
}

# Check if run file exists, if so, then exit
if [ -f "$file_log" ]
then
    exit 1
fi

> "$file_log"

File export-db.sh.

#!/bin/bash

source function.sh

folder_export="/mnt/export"
username="sofimon"
divider=";"

# Read config file, variables as var divided by ;
while IFS=$divider read -ra var; do

    command_mkdir="mkdir -p "$folder_export"/"${var[0]}""
    command_mysqldump="sudo mysqldump -uroot -p"${var[1]}" --max_allowed_packet=2147483648 --host=localhost --quote-names --ignore-table=mysql.event --opt --all-databases"
    command_ssh="ssh -i id_rsa_sofimon -n "$username"@"${var[0]}" "$command_mysqldump" > "$folder_export"/"${var[0]}"/"$date_time"-"${var[0]}".mysql"


# Check commands
    echo $command_mkdir
    echo $command_ssh

# Run commands
    doit "create export folder "${var[0]}"" "$command_mkdir"
    doit "dump database from "${var[0]}"" "$command_ssh"

done <<< $(cat "${file_name%.*}"-$1.cfg | grep -v "#")

email

File export-db-ssc.cfg.

# host;password
ssc-osw-web;PASSWORD

When I run

./export-db.sh ssc

it shows me this.

hosek@osw-backup:~/sofimon$ ./export-db.sh ssc
mkdir -p /mnt/export/ssc-osw-web
ssh -n sofimon@ssc-osw-web sudo mysqldump -uroot -pPASSWORD --max_allowed_packet=2147483648 --host=localhost --quote-names --ignore-table=mysql.event --opt --all-databases > /mnt/export/ssc-osw-web/20200221-110536-ssc-osw-web.mysqldump
20200221-110536|sofimon|export-db.sh|create export folder ssc-osw-web|true.
bash: /mnt/export/ssc-osw-web/20200221-110536-ssc-osw-web.mysqldump: No such file or directory
20200221-110538|sofimon|export-db.sh|dump database from ssc-osw-web|false!

So command_mkdir is OK, but command_ssh is not working.

Why error No such file or directory?

When I run command $command_ssh manually in terminal, it works perfectly.

ssh -n sofimon@ssc-osw-web sudo mysqldump -uroot -pPASSWORD --max_allowed_packet=2147483648 --host=localhost --quote-names --ignore-table=mysql.event --opt --all-databases > /mnt/export/ssc-osw-web/20200221-110536-ssc-osw-web.mysqldump

Tried to modify script for this result when echo $command_ssh.

ssh -n sofimon@ssc-osw-web "sudo mysqldump -uroot -pPASSWORD --max_allowed_packet=2147483648 --host=localhost --quote-names --ignore-table=mysql.event --opt --all-databases" > /mnt/export/ssc-osw-web/20200221-110536-ssc-osw-web.mysqldump

Same error.

Thanks.

UPDATE

New code with functions.

#!/bin/bash

cd "$(dirname "${BASH_SOURCE[0]}")"

date_time="$(date "+%Y%m%d-%H%M%S")"
now="date +%Y%m%d-%H%M%S"
module="$1"
config="$2"
log="log/${module%.*}.log"
email_sender='[email protected]'
email_recipients='[email protected]'
#email_recipients='[email protected] [email protected]'


# Declare functions

message()
{
if [ $1 = "i" ]
then
echo "`$now`|sofimon|"$module"|"$config"|$2|info." 2>&1 | tee -a "$log"
elif [ $1 = "t" ]
then
echo "`$now`|sofimon|"$module"|"$config"|$2|true." 2>&1 | tee -a "$log"
else [ $1 = "f" ]
echo "`$now`|sofimon|"$module"|"$config"|$2|false!" 2>&1 | tee -a "$log"
fi
}

doit()
{
#message "i" "$1"
if
"$1"
then
message "t" "$1"
else
message "f" "$1"
result="false"
fi
#message "i" "$1"
}

email()
{
cat "$log" | mail -a "From: sofimon <$email_sender>" -a "Content-type: text/plain" -s "sofimon" -r $email_sender $email_recipients
}

# Declare module functions

export_db()
{
folder_export="/mnt/export"
username="sofimon"
mkdir -p "$folder_export"/"${var[0]}"
ssh -i id_rsa_sofimon -n "$username"@"${var[0]}" "sudo mysqldump -uroot -p"${var[1]}" --max_allowed_packet=2147483648 --host=localhost --quote-names --ignore-table=mysql.event --opt --all-databases" > "$folder_export"/"${var[0]}"/"$date_time"-"${var[0]}".mysql
}

# Check if run file exists, if so, then exit

if [ -f "$log" ]
then
message "f" "script is still runnning"
exit 1
else
> "$log"
fi

# Read config file, variables as var divided by ' '

while IFS=' ' read -ra var; do
doit "$module"
done <<< $(cat "${module%.*}"-"$config".cfg | grep -v "#")
#email
mv "$log" "$log"_"$date_time"
rm -rf "$log"

But it returns this.

hosek@osw-backup:~/sofimon$ ./sofimon.sh export-db ssc
./sofimon.sh: line 34: export-db: command not found
20200224-133436|sofimon|export-db|ssc|export-db|false!
hosek@osw-backup:~/sofimon$ 

Why, if function export-db is declared?

14
  • Welcome! Is your if statement like shown, or is a typo? Commented Feb 21, 2020 at 13:26
  • @guillermochamorro No, it is not typo. Commented Feb 21, 2020 at 13:31
  • Ah! Thanks, yes. One more thing, what shebang are you using? Is it #!/bin/bash or something else? source is not standard or portable. Commented Feb 21, 2020 at 13:42
  • 1
    That has A LOT of problems, but of course command_ssh doesn't work because of the > (which has already been explained to death ;-)): Simpler example: ssh user@host : > file will create file on the local machine, but ssh='ssh user@host : > file'; $ssh will create file on the remote machine. Commented Feb 21, 2020 at 13:54
  • @mosvy I updated command_ssh, result is now ssh -i id_rsa_sofimon -n sofimon@ssc-osw-web "sudo mysqldump -uroot -pPASS --max_allowed_packet=2147483648 --host=localhost --quote-names --ignore-table=mysql.event --opt --all-databases" > /mnt/export/ssc-osw-web/20200221-143024-ssc-osw-web.mysql . And why it is working when I run this command manually? Commented Feb 21, 2020 at 14:07

1 Answer 1

0

This is failing because the command string has the redirection to /mnt/export/ssc-osw-web/20200221-110536-ssc-osw-web.mysqldump is being applied on the remote system, whereas you have created the containing directory on the local system.

There is no easy way to fix this with the code you have written, because you cannot* embed a redirection in a variable holding a command string.

(* I suppose you can with eval or by calling bash -c, but you really, really don't want to go there.)

1
  • Done, updated in question. Commented Feb 24, 2020 at 13:44

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.