[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Multithreading with libssh


The problem with your approach is that you have to error-check all 1500
commands that you execute, handle the issues and handle the session itself
terminating mid-run.  Better would be to have a local command on host that
wraps the 1500 commands that you want to run.

I would suggest this approach instead:
ssh to host
system-run wrappercmd.sh
wait for command to complete with systemctl status
extract output with journalctl --unit=... or have the wrapper write the
output to a file that you can then retrieve using SFTP or cat.

If you expect the commands to take minutes to complete, then re-connect to
the host each time you want to poll for completion.


On Thu, 26 Sep 2019 at 12:09, Simon Moselewski <s.moselewski@xxxxxxxx>
wrote:

> Hi everyone,
>
> I am using libssh to connect to a remote host, run commands on it and read
> the results. Since I am doing this for 1500 commands I want to use threads
> to parallelize that.
>
> I am using gcc compiler with flags -libssh -pthread and -lssh_threads.
>
> My threadless approach was:
> open session
> repeat 1500 times {
>     open channel
>     run remote command
>     close channel
> }
> close session
>
> I read in the docu, that sessions cannot be shared over multiple threads,
> so with the threadful approach I do it differently:
> repeat 1500 times {
>     open session
>     open channel
>     run remote command
>     close channel
>     close session
> }
>
> The threadful programm takes longer than my threadless approach so I guess
> something with the threading is not working correctly.
>
> I am very inexperienced with threads and would need some help here.
>
> Thanks in advance for any hints!!!
> Regards
> Simon
>
>
>
> My threadful code (shortened):
>
> ssh_threads_set_callbacks(ssh_threads_get_pthread());
> ssh_init();
> std::mutex mutex;
> std::vector<std::future<void>> tasks;
> tasks.reserve(16);
> for (list<Metric>::iterator it = metrics.begin(); it != metrics.end();
> it++) {
>     Metric metric = *it;
>     tasks.emplace_back(std::async(std::launch::async, [&ip, &user, &pw,
> metric, i, &mutex]() {
>         std::lock_guard<std::mutex> lock(mutex);
>         try {
>             ssh_session session = ssh_new();
>             ssh_options_set(session, SSH_OPTIONS_HOST, IP);
>             rc = ssh_userauth_password(session, USERNAME, PASSWORD);
>             ssh_channel channel = ssh_channel_new(session);
>             rc = ssh_channel_open_session(channel);
>             rc = ssh_channel_request_exec(channel, COMMAND);
>             // get output
>             char buffer[32] = {0};
>             int nbytes;
>             nbytes = ssh_channel_read(channel, buffer, sizeof(buffer)-1,
> 0);
>             ssh_channel_send_eof(channel);
>             //get exit code
>             int exitCode = -1;
>             exitCode = ssh_channel_get_exit_status(channel);
>             ssh_channel_close(channel);
>             ssh_channel_free(channel);
>             ssh_disconnect(session);
>             ssh_free(session);
>          }
>          catch(...) {
>               //something
>          }
>      }));
> }
> std::for_each(std::begin(tasks), std::end(tasks), [](auto& task) {
>      task.get();
> });
> std::cout << "Done.\n";
> ssh_finalize();
>

References:
Multithreading with libsshSimon Moselewski <s.moselewski@xxxxxxxx>
Archive administrator: postmaster@lists.cynapses.org