|
Boost Users : |
From: dinesh kumar (dineshkumar02_at_[hidden])
Date: 2019-10-15 16:47:24
I had the similar problem with boost process arguments and I followed below
approach.
Please go through below code snippet and let me know if it's not clear.
IIRC, we have to pass the whole command as a single inline command rather
passing arguments as separate argument.
string cmd;
string args;
// Split command and it's arguments as two different things
u_split_command_arguments( get_command(), cmd, args );
// Find the command's complete executable path.
auto complete_command = boost_process::search_path( cmd );
if ( complete_command.empty() )
return error( error_command_notfound, ERR_COMMAND_NOTFOUND,
HINT_COMMAND_NOTFOUND,
job_id_type( job_id ) );
// XXX
// boost::child constructor accepts the command,
// arguments as a
// separate list. For example, if we configured the job command as psql
-c
// "COPY table_name
// TO STDOUT", then the whole command would be `/usr/local/bin/psql`
and it's
// argument values like
// `-c "COPY table_name TO STDOUT"`.
//
// If we pass both values individually to the boost::child constructor,
we are
// getting the
// FATAL error as `database " -c " COPY source TO STDOUT WITH CSV""
does not
// exist`, which
// seems boost is considering to pass these arguments as actual program
// argument, than the
// command flag arguments. Hence, merging the both command and it's
arguments
// as single
// object, and then passing the whole command at once.
cmd = complete_command.generic_string() + " " + args;
m_process_group_ = new boost_process::group{};
boost_process::child child_process{};
// without environment variables
if ( !m_environment_.size() )
child_process = boost_process::child{cmd, *m_process_group_,
boost_process::std_out > cstdout,
boost_process::std_err > cstderr};
void u_split_command_arguments( const string &cmd, string &split_cmd, string
&args ) {
auto pos{0};
for ( auto &x : cmd ) {
if ( x == ' ' )
break;
split_cmd += x;
pos++;
}
args = cmd.substr( pos );
}
On Tue, Oct 15, 2019 at 7:27 PM name name via Boost-users <
boost-users_at_[hidden]> wrote:
> Hi,
>
>
>
> Im use boost::process::child to create a mysql cli child process to import
> sql file.
>
> Normally im use this command:
>
> /usr/bin/mysql mysql -h127.0.0.1 -utestuser --password='!@#QWE123qwe'
> -P3306 --default-character-set=utf8mb4 --max-allowed-packet=1GB <
> /root/create_db.sql
>
> Itâs worked well in bash.
>
>
>
> But when use boost::process::child, std_err report ERROR 1045 (28000):
> Access denied for user 'testuser'@'localhost' (using password: YES).
>
> Is there any bugs in my code?
>
>
>
> Os: ubuntu 18.04 LTS
>
> Boost: 1.71.0
>
> MySql:5.7.27
>
>
>
> Create_db.sql:
>
> DROP DATABASE IF EXISTS test_db;
>
> CREATE DATABASE test_db;
>
>
>
> Thanks
>
>
>
> [code]
>
> #include <iostream>
>
>
>
> #include <boost/algorithm/string/join.hpp>
>
> #include <boost/iostreams/copy.hpp>
>
> #include <boost/asio/io_context.hpp>
>
> #include <boost/process.hpp>
>
>
>
> using namespace boost::process;
>
> using namespace boost::iostreams;
>
> using namespace boost::asio;
>
>
>
> std::string SearchExecutableInPath(std::string const& filename) {
>
> try {
>
> return search_path(filename).generic_string();
>
> }
>
> catch (...) {
>
> return "";
>
> }
>
> }
>
>
>
> int RunProcess(
>
> std::string const& executable,
>
> std::vector<std::string> const& args,
>
> std::string input_file_path
>
> ) {
>
> io_context ioCtx;
>
>
>
> auto work = make_work_guard(ioCtx);
>
>
>
> std::thread ioThread([&ioCtx] {
>
> ioCtx.run();
>
> });
>
>
>
> std::future<std::string> dataOut, dataErr;
>
>
>
> child c;
>
>
>
> if (!input_file_path.empty()) {
>
> c = child(
>
> boost::filesystem::absolute(executable),
>
> boost::process::args(args),
>
> std_out > dataOut,
>
> std_err > dataErr,
>
> std_in < boost::filesystem::absolute(input_file_path),
>
> ioCtx
>
> );
>
> }
>
> else {
>
> c = child(
>
> boost::filesystem::absolute(executable),
>
> boost::process::args(args),
>
> std_out > dataOut,
>
> std_err > dataErr,
>
> std_in.close(),
>
> ioCtx
>
> );
>
> }
>
>
>
> c.wait();
>
>
>
> int result = c.exit_code();
>
>
>
> std::string output = dataOut.get();
>
> std::string error = dataErr.get();
>
>
>
> if (!output.empty()) {
>
> std::cout << output << std::endl;
>
> }
>
>
>
> if (!error.empty()) {
>
> std::cout << error << std::endl;
>
> }
>
>
>
> work.reset();
>
> ioThread.join();
>
>
>
> return result;
>
> }
>
>
>
>
>
> int main()
>
> {
>
> // /usr/bin/mysql mysql -h127.0.0.1 -utestuser
> --password='!@#QWE123qwe' -P3306 --default-character-set=utf8mb4
> --max-allowed-packet=1GB < /root/create_db.sql
>
>
>
> std::vector<std::string> args;
>
> args.reserve(8);
>
>
>
> // mysql cli
>
> args.push_back("mysql");
>
>
>
> // connection info
>
> args.push_back("-h127.0.0.1");
>
> args.push_back("-utestuser");
>
> args.push_back("--password='!@#QWE123qwe'");
>
> args.push_back("-P3306");
>
>
>
> // encoding
>
> args.push_back("--default-character-set=utf8mb4");
>
>
>
> // maybe large sql file
>
> args.push_back("--max-allowed-packet=1GB");
>
>
>
> int const ret = RunProcess(
>
> SearchExecutableInPath("mysql"),
>
> args,
>
> "/root/create_db.sql");
>
>
>
> std::cout << "ret code: " << ret << std::endl;
>
>
>
> return 0;
>
> }
>
> [/code]
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> https://lists.boost.org/mailman/listinfo.cgi/boost-users
>
-- Regards, Dinesh manojadinesh.blogspot.com
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net