Boost logo

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