Run mysqldump from dotnet runtime error -1073741515 - mysql

I'm trying to create a backup of my mysql databases using Azure Functions. Everything works fine when I run mysqldump.exe in the terminal (SCM/Kudu) but when I run the exact same command from dotnet using Process.Start, the app exits immediately with exit code -1073741515.
This is how I run the code from the terminal using Kudu. This command is literally the command that is also executed from dotnet because I copied it from the logs:
D:\home\site\wwwroot\mysqldump\win\mysqldump.exe --host=*** --user=*** --password=*** --single-transaction --quick --lock-tables=false --routines --hex-blob --result-file=d:\home\site\temp\697ce5ad-0bba-4de1-b070-7c65283a3941 --verbose ***
Result:
Process exits with exit code 0 and the backup file is created as expected.
This is how I run the command from dotnet:
var mysqlDump = "D:\home\site\wwwroot\mysqldump\win\mysqldump.exe";
var process = new Process();
var startInfo = new ProcessStartInfo
{
FileName = mysqlDump,
Arguments =
$"--host={dbHost} --user={dbUser} --password={dbPassword} --single-transaction --quick --lock-tables=false --routines --hex-blob --result-file={sqlPath}{(mysqlDumpVerbose ? " --verbose" : "")} {message.Database}",
WindowStyle = ProcessWindowStyle.Minimized,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardError = true,
RedirectStandardOutput = true
};
process.StartInfo = startInfo;
process.EnableRaisingEvents = true;
process.OutputDataReceived += (sender, e) =>
{
if (!string.IsNullOrWhiteSpace(e.Data))
{
log.LogInformation(e.Data);
}
};
process.ErrorDataReceived += (sender, e) =>
{
if (!string.IsNullOrWhiteSpace(e.Data))
{
log.LogError(e.Data);
}
};
try
{
log.LogInformation($"Executing '{startInfo.FileName} {startInfo.Arguments}'...");
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
process.WaitForExit(1000 * 60 * 10);
if (process.ExitCode != 0)
{
throw new ApplicationException(
$"Process did not exit with code 0 (zero). Actual exit code: {process.ExitCode}");
}
}
finally
{
log.LogInformation($"Cleaning up files...");
TryDeleteFile(sqlPath, log);
TryDeleteFile(sqlCleanedPath, log);
TryDeleteFile(zipPath, log);
}
Output:
[Information] Executing 'D:\home\site\wwwroot\mysqldump\win\mysqldump.exe --host=*** --user=*** --password=*** --single-transaction --quick --lock-tables=false --routines --hex-blob --result-file=d:\home\site\temp\697ce5ad-0bba-4de1-b070-7c65283a3941 --verbose ***'...
[Error] Exception: Process did not exit with code 0 (zero). Actual exit code: -1073741515
These are the versions:
mysqldump version: 8.0.23 (8.0.26 and 8.0.27 don't work either)
dotnet runtime: 3.1
Azure functions runtime: 3
I also tried a 5.7.* version of mysqldump which actually starts but then crashes with exit code 2 when it reached a certain table in the database, regardless of how I execute the command.
I really have no clue why the exact same command does work in the terminal but not work from dotnet or why mysqldump version 5.7.35 does start but 8.0.* doesn't. Any ideas anyone?

Related

Mysql NodeJS reject sound query to Duplicate Databases

Below is a sound query to CLONE a Database that if executed at the command line work perfectly every time.
Executing (default): mysqldump
--column-statistics=0
-h ***.amazonaws.com
-u ***
-p*** MyDB1
--set-gtid-purged=OFF
|
mysql -h ***.amazonaws.com
-u ***
-p*** MyDB2
NodeJS
let DBname = req.body.DBname;
var sql = `mysqldump --column-statistics=0 -h ${config.global.host} -u ${config.global.user} -p${config.global.password} ${config.global.root_db_name} --set-gtid-purged=OFF | mysql -h ${config.global.host} -u ${config.global.user} -p${config.global.password} ${DBname} `
db.sequelize.query(sql)
.then( ()=> {
console.log(`${config.global.root_db_name} copied to-> ${DBname}`)
res.send('success')
}).catch( err=> {
console.log(`ERR: ${config.global.root_db_name} *FAILED* copied to-> ${DBname} ==> `+"\n\n" + err +"\n")
res.send('fail')
})
However when I embed it in to my NodeJS program it throws error:
SequelizeDatabaseError: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax
Has anyone dealt with this before - all advice welcome thank you.
This solution came as a result of Andrew A remarks above. I was not executing an SQL command.
here is what works
const shell = require('shelljs')
...
var dump = `mysqldump --column-statistics=0 -h ${config.global.host} -u ${config.global.user} -p${config.global.password} ${config.global.root_db_name} --set-gtid-purged=OFF | mysql -h ${config.global.host} -u ${config.global.user} -p${config.global.password} ${DBname} `
if (shell.exec(dump).code !== 0) {
console.log(`ERR: ${config.global.root_db_name} *FAILED* copied to-> ${DBname} `)
res.send('fail')
} else {
console.log(`${config.global.root_db_name} copied to-> ${DBname}`)
res.send('success')
}

How to execute mysql script insertion on terraform user_data?

The last line of the script was not executed.
I tried to execute the code manually on the instance created and it was successful.
#!/bin/bash
#install tools
apt-get update -y
apt-get install mysql-client -y
#Create MySQL config file
echo "[mysql]" >> ~/.my.cnf
echo "user = poc5admin" >> ~/.my.cnf
echo "password = poc5password" >> ~/.my.cnf
#test
echo "endpoint = ${rds_endpoint}" >> ~/variables
hostip=$(hostname -I)
endpoint=${rds_endpoint}
echo "$hostip" >> ~/variables
#I have created a table here but I will remove the code since it is unnecessary...
#Create User
echo "CREATE USER 'poc5user'#'%' IDENTIFIED BY 'poc5pass';" >> ~/mysqlscript.sql
echo "GRANT EVENT ON * . * TO 'poc5user'#'%';" >> ~/mysqlscript.sql
cp mysqlscript.sql /home/ubuntu/mysqlscript.sql
mysql -h $endpoint -u poc5admin < ~/mysqlscript.sql
Expected result: There should be a Database, Table and User created on the RDS instance.
You can insert or create Database like this from the bash script but it is not recommended an approach to work with RDS. better to place your data over s3 and import from the s3.
Here is the example, that will create DB
resource "aws_db_instance" "db" {
allocated_storage = 20
storage_type = "gp2"
engine = "mysql"
engine_version = "5.7"
instance_class = "db.t2.micro"
name = "mydb"
username = "foo"
password = "foobarbaz"
parameter_group_name = "default.mysql5.7"
s3_import {
source_engine = "mysql"
source_engine_version = "5.6"
bucket_name = "mybucket"
bucket_prefix = "backups"
ingestion_role = "arn:aws:iam::1234567890:role/role-xtrabackup-rds-restore"
}
}
~/.my.cnf why you need this? better to place these script in the s3 file.
second thing, If you still interesting to run from your local environment then you can insert from local-exec
resource "null_resource" "main_db_update_table" {
provisioner "local-exec" {
on_failure = "fail"
interpreter = ["/bin/bash", "-c"]
command = <<EOT
mysql -h ${aws_rds_cluster.db.endpoint} -u your_username -pyour_password your_db < mysql_script.sql
EOT
}
}
But better to with s3.
If you want to import from remote, you can explore remote-exec.
With user-data, you can do this but it seems your MySQL script not generating properly. better to cp script to remote and then run with local exec in remote.
There is no such thing as terraform "user_data". User data is a bootstrap script for the EC2 instances which you can use to install software/binaries or to execute your script at the boot time.
The script will be executed by the cloud-init, not by the terraform itself. The responsibility of the terraform is to set user-data for the ec2 instances.
You may check the cloud-init output logs which should have the result of your user-data script also.
From your code, I am not able to understand which step you have copied the below file.
cp mysqlscript.sql /home/ubuntu/mysqlscript.sql
mysql -h $endpoint -u poc5admin < ~/mysqlscript.sql
I am assuming that you are creating a new server and it does not have any file.
Thank you for your inputs. I have found an answer by moving the config file to /etc/mysql/my.cnf and then executing
mysql -h $endpoint -u poc5admin < ~/mysqlscript.sql

Cloning a MySQL database on the same MySql instance in Window 10

I go through so many solution of it but none of them is working in window 10 previously I was working on window 7 but after move on window 10 this mysql query is not working on window 10 command line.
c:\wamp\bin\mysql\mysql5.7.19\bin\mysql.exe -uroot -ppassword
test_db1 | mysql.exe -u root -ppassword test_db2;
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'c:\wamp\bin\mysql\mysql5.7.19\bin\mysql.exe -uroot -ppassword ifinance_hea' at line 1
I have given full path of mysql.exe
Note:- I know There are many solutions are available but none of them working for me.
I also tried this:-
mysqldump -uroot -ppassword test_db1 | mysql -u root -ppassword test_db2;
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'mysqldump -uroot -ppassword ifinance_hea | mysql -u root -ppassword ifinance_hea' at line 1
My code is:-
public void copyDB(BRANCH branch, Date processDate, String newDbName) throws IOException {
Session session = getSessionFactory(branch).openSession();
try {
String sqlC = "CREATE DATABASE IF NOT EXISTS " + newDbName;
Query queryC = session.createSQLQuery(sqlC);
queryC.executeUpdate();
ProcessBuilder builder = new ProcessBuilder(Util.getProcessBuilder());
Process p = builder.start();
// get stdin of shell
BufferedWriter p_stdin = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
p_stdin.write(c:\wamp\bin\mysql\mysql5.7.19\bin\mysql.exe -uroot -ppassword test_db1 | mysql.exe -u root -ppassword test_db2);
p_stdin.newLine();
p_stdin.flush();
// finally close the shell by execution exit command
p_stdin.write("exit");
p_stdin.newLine();
p_stdin.flush();
Scanner s = new Scanner(p.getInputStream());
while (s.hasNextLine()) {
System.out.println(s.nextLine());
}
s.close();
} finally {
session.flush();
session.close();
}
}

how to take backup of mysql remote database using java swing

How to take backup of myphpadmin remote or online server database using java swing.
This is showing error of connection. What to do for mysqld.exe for backup.
Process p;
try {
Runtime runtime = Runtime.getRuntime();
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
url="jdbc:mysql://188.188.188.188:3306/Datatable";
user="datatable";
password="123";
con=DriverManager.getConnection(url,user,password) ;
p=runtime.exec("mysqldump -datatable -p123 --add-drop-database server -B datatable -r"+path);
// "C:/xampp/mysql/bin/mysqldump.exe -uroot -p --add-drop-database server -B newproject -r"+path);
int processComplete = p.waitFor();
if (processComplete==1) {
jLabel1.setText("Backup Created Succuss");
}else{
jLabel1.setText("Can't Create backup");
}
} catch (Exception e) {
e.printStackTrace();
}
What can i do for backup the database.

How to Export & Import Existing User (with its Privileges!)

I have an existing MySQL instance (test), containing 2 databases and a few users each having different access privileges to each database.
I now need to duplicate one of the databases (into production) and the users associated with it.
Duplicating the database was easy:
Export:
mysqldump --no-data --tables -u root -p secondb >> secondb_schema.sql
Import:
mysql -u root -p -h localhost secondb < secondb_schema.sql
I didn't find, however, a straightforward way to export and import users, from the command line (either inside or outside mysql).
How do I export and import a user, from the command line?
Update: So far, I have found manual (and thus error prone) steps for accomplishing this:
-- lists all users
select user,host from mysql.user;
Then find its grants:
-- find privilege granted to a particular user
show grants for 'root'#'localhost';
Then manually create user with the grants listed in the result of the 'show grants' command above.
I prefer a safer, more automated way. Is there one?
One of the easiest ways I've found to export users is using Percona's tool pt-show-grants. The Percona tool kit is free, easy to install, and easy to use, with lots of documentation.
It's an easy way to show all users, or specific users. It lists all of their grants and outputs in SQL format. I'll give an example of how I would show all grants for test_user:
shell> pt-show-grants --only test_user
Example output of that command:
GRANT USAGE ON *.* TO 'test_user'#'%' IDENTIFIED BY PASSWORD '*06406C868B12689643D7E55E8EB2FE82B4A6F5F4';
GRANT ALTER, INSERT, LOCK TABLES, SELECT, UPDATE ON `test`.* TO 'test_user'#'%';
I usually rederict the output into a file so I can edit what I need, or load it into mysql.
Alternatively, if you don't want to use the Percona tool and want to do a dump of all users, you could use mysqldump in this fashion:
shell> mysqldump mysql --tables user db > users.sql
Note: --flush-privileges won't work with this, as the entire db isn't being dumped. this means you need to run it manually.
shell> mysql -e "FLUSH PRIVILEGES"
mysql -u<user> -p<password> -h<host> -e"select concat('show grants for ','\'',user,'\'#\'',host,'\'') from mysql.user" > user_list_with_header.txt
sed '1d' user_list_with_header.txt > ./user.txt
while read user; do mysql -u<user> -p<password> -h<host> -e"$user" > user_grant.txt; sed '1d' user_grant.txt >> user_privileges.txt; echo "flush privileges" >> user_privileges.txt; done < user.txt
awk '{print $0";"}' user_privileges.txt >user_privileges_final.sql
rm user.txt user_list_with_header.txt user_grant.txt user_privileges.txt
Above script will run in linux environment and output will be user_privileges_final.sql that you can import in new mysql server where you want to copy user privileges.
UPDATE: There was a missing - for the user of the 2nd mysql statement.
In mysql 5.7 and later you can use this.
mysqlpump -uroot -p${yourpasswd} --exclude-databases=% --users
This will generate a sql format output that you can redirect to mysql_users.sql.
Note that it is mysqlpump not mysqldump.
Yet another bash one-liner for linux that you can use instead of the Percona tool:
mysql -u<user> -p<password> -h<host> -N mysql -e "select concat(\"'\", user, \"'#'\", host, \"'\"), coalesce(password, authentication_string) from user where not user like 'mysql.%'" | while read usr pw ; do echo "GRANT USAGE ON *.* TO $usr IDENTIFIED BY PASSWORD '$pw';" ; mysql -u<user> -p<password> -h<host> -N -e "SHOW GRANTS FOR $usr" | grep -v 'GRANT USAGE' | sed 's/\(\S\)$/\1;/' ; done
In complement of #Sergey-Podushkin 's answer, this shell script code is workin for me:
mysql -u<user> -p<password> -N mysql -e "select concat(\"'\", user, \"'#'\", host, \"'\"), authentication_string from user where not user like 'root'" | while read usr pw ; do mysql -u<user> -p<password> -N -e "SHOW GRANTS FOR $usr" | sed 's/\(\S\)$/\1;/'; done
PhpMyAdminYou can use phpMyAdmin.
Login and Go to your database or a table where the user has access.
Select privileges
All users with access are there.
Select Export. And a little window with all the GRANTS are there ready to copy and paste.
I tackled this with a small C# program. There is code here to generate a script or apply the grants directly from source to destination. If porting from a Windows -> *nix environment you may have to consider case sensitivity issues.
using System;
using MySql.Data.MySqlClient;
using System.Configuration;
using System.IO;
using System.Collections.Generic;
namespace GenerateUsersScript
{
class Program
{
static void Main(string[] args)
{
List<string> grantsQueries = new List<string>();
// Get A Show Grants query for each user
using (MySqlConnection sourceConn = OpenConnection("sourceDatabase"))
{
using (MySqlDataReader usersReader = GetUsersReader(sourceConn))
{
while (usersReader.Read())
{
grantsQueries.Add(String.Format("SHOW GRANTS FOR '{0}'#'{1}'", usersReader[0], usersReader[1]));
}
}
Console.WriteLine("Exporting Grants For {0} Users", grantsQueries.Count);
using (StreamWriter writer = File.CreateText(#".\UserPermissions.Sql"))
{
// Then Execute each in turn
foreach (string grantsSql in grantsQueries)
{
WritePermissionsScript(sourceConn, grantsSql, writer);
}
//using (MySqlConnection destConn = OpenConnection("targetDatabase"))
//{
// MySqlCommand command = destConn.CreateCommand();
// foreach (string grantsSql in grantsQueries)
// {
// WritePermissionsDirect(sourceConn, grantsSql, command);
// }
//}
}
}
Console.WriteLine("Done - Press A Key to Continue");
Console.ReadKey();
}
private static void WritePermissionsDirect(MySqlConnection sourceConn, string grantsSql, MySqlCommand writeCommand)
{
MySqlCommand cmd = new MySqlCommand(grantsSql, sourceConn);
using (MySqlDataReader grantsReader = cmd.ExecuteReader())
{
while (grantsReader.Read())
{
try
{
writeCommand.CommandText = grantsReader[0].ToString();
writeCommand.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(grantsReader[0].ToString());
Console.WriteLine(ex.Message);
}
}
}
}
private static void WritePermissionsScript(MySqlConnection conn, string grantsSql, StreamWriter writer)
{
MySqlCommand command = new MySqlCommand(grantsSql, conn);
using (MySqlDataReader grantsReader = command.ExecuteReader())
{
while (grantsReader.Read())
{
writer.WriteLine(grantsReader[0] + ";");
}
}
writer.WriteLine();
}
private static MySqlDataReader GetUsersReader(MySqlConnection conn)
{
string queryString = String.Format("SELECT User, Host FROM USER");
MySqlCommand command = new MySqlCommand(queryString, conn);
MySqlDataReader reader = command.ExecuteReader();
return reader;
}
private static MySqlConnection OpenConnection(string connName)
{
string connectionString = ConfigurationManager.ConnectionStrings[connName].ConnectionString;
MySqlConnection connection = new MySqlConnection(connectionString);
connection.Open();
return connection;
}
}
}
with an app.config containing ...
<connectionStrings>
<add name="sourceDatabase" connectionString="server=localhost;user id=hugh;password=xxxxxxxx;persistsecurityinfo=True;database=MySql" />
<add name="targetDatabase" connectionString="server=queeg;user id=hugh;password=xxxxxxxx;persistsecurityinfo=True;database=MySql" />
</connectionStrings>
Here's what I'm using these days as part of my daily backup scripts (requires root shell and MySQL access, linux shell, and uses the mysql built-in schema:
First, I create a file /var/backup/mysqlroot.cnf containing the root password so I can automate my scripts and not hardcode any passwords in them:
[client]
password=(put your password here)
Then I create an export script which dumps create user commands and grants like this:
touch /var/backup/backup_sql.sh
chmod 700 /var/backup/backup_sql.sh
vi /var/backup/backup_sql.sh
And then write the following contents:
#!/bin/bash
mysql --defaults-extra-file=/var/backup/mysqlroot.cnf -sNe " \
SELECT \
CONCAT( 'CREATE USER \'', User, '\'#\'', Host, '\' IDENTIFIED BY \'', authentication_string, '\'\;' ) AS User \
FROM mysql.user \
WHERE \
User NOT LIKE 'mysql.%' AND CONCAT( User, Host ) <> 'rootlocalhost' AND User <> 'debian-sys-maint' \
"
mysql --defaults-extra-file=/var/backup/mysqlroot.cnf -sNe " \
SELECT \
CONCAT( '\'', User, '\'#\'', Host, '\'' ) as User FROM mysql.user \
WHERE \
User NOT LIKE 'mysql.%' \
AND CONCAT( User, Host ) <> 'rootlocalhost' \
AND User <> 'debian-sys-maint' \
" | sort | while read u ;
do echo "-- $u"; mysql --defaults-extra-file=/var/backup/mysqlroot.cnf -sNe "show grants for $u" | sed 's/$/;/'
done
Then I just have to run it like this:
/var/backup/backup_sql.sh > /tmp/exportusers.sql
A PHP script to loop over your users to get the grant commands would be as such:
// Set up database root credentials
$host = 'localhost';
$user = 'root';
$pass = 'YOUR PASSWORD';
// ---- Do not edit below this ----
// Misc settings
header('Content-type: text/plain; Charset=UTF-8');
// Final import queries goes here
$export = array();
// Connect to database
try {
$link = new PDO("mysql:host=$host;dbname=mysql", $user, $pass);
} catch (PDOException $e) {
printf('Connect failed: %s', $e->getMessage());
die();
}
// Get users from database
$statement = $link->prepare("select `user`, `host`, `password` FROM `user`");
$statement->execute();
while ($row = $statement->fetch())
{
$user = $row[0];
$host = $row[1];
$pass = $row[2];
$export[] = "CREATE USER '{$user}'#'{$host}' IDENTIFIED BY '{$pass}'";
// Fetch any permissions found in database
$statement2 = $link->prepare("SHOW GRANTS FOR '{$user}'#'{$host}'");
$statement2->execute();
while ($row2 = $statement2->fetch())
{
$export[] = $row2[0];
}
}
$link = null;
echo implode(";\n", $export);
Gist: https://gist.github.com/zaiddabaeen/e88a2d10528e31cd6692
pass=your_password_here; \
MYSQL_PWD=$pass mysql -B -N -uroot -e "SELECT CONCAT('\'', user,'\' ','\'', host,'\' ','\'', authentication_string,'\' ','\'', plugin,'\'') FROM mysql.user WHERE user != 'debian-sys-maint' AND user != 'root' AND user != 'mysql.sys' AND user != 'mysql.session' AND user != ''" > mysql_all_users.txt; \
while read line; do linearray=(${line}); \
MYSQL_PWD=$pass mysql -B -N -uroot -e "SELECT CONCAT('CREATE USER \'',${linearray[0]},'\'#\'',${linearray[1]},'\' IDENTIFIED WITH \'',${linearray[3]},'\' AS \'',${linearray[2]},'\'')"; \
done < mysql_all_users.txt > mysql_all_users_sql.sql; \
while read line; do linearray=(${line}); \
MYSQL_PWD=$pass mysql -B -N -uroot -e "SHOW GRANTS FOR ${linearray[0]}#${linearray[1]}"; \
done < mysql_all_users.txt >> mysql_all_users_sql.sql; \
sed -e 's/$/;/' -i mysql_all_users_sql.sql; \
echo 'FLUSH PRIVILEGES;' >> mysql_all_users_sql.sql; \
unset pass
First mysql command : export all users to file and exclude some.
Second mysql command : loop users from file to write a sql command 'create user' to an exported file (with authentication credentials).
Third mysql command : loop users from file to append their privileges to the exported file.
sed command to append a ";" to end of lines and flush privileges to finish.
To import : MYSQL_PWD=$pass mysql -u root < mysql_all_users_sql.sql
SELECT CONCAT('\create user ', user,'\'#\'', host, '\' identified by ', "'", authentication_string, "'"'\;') FROM user WHERE user != 'mysql.session' AND user !='mysql.sys' AND user != 'root' AND user != '';
I had the same problem. The solution is that after the import of the backup you need to do a "flush privileges;". Then the privileges of the users will be active as in the original database.
So execute:
mysql -u root -p -h localhost secondb < secondb_schema.sql
mysql -u root
then in mysql:
flush privileges;