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@lists.boost.org> 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

Its 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@lists.boost.org
https://lists.boost.org/mailman/listinfo.cgi/boost-users


--

Regards,
Dinesh
manojadinesh.blogspot.com