]>
sourceware.org Git - systemtap.git/blob - remote.cxx
1 // systemtap remote execution
2 // Copyright (C) 2010-2015 Red Hat Inc.
4 // This file is part of systemtap, and is free software. You can
5 // redistribute it and/or modify it under the terms of the GNU General
6 // Public License (GPL); either version 2, or (at your option) any
14 #include <sys/types.h>
17 #include <sys/socket.h>
35 // Decode URIs as per RFC 3986, though not bothering to be strict
39 string scheme
, authority
, path
, query
, fragment
;
40 bool has_authority
, has_query
, has_fragment
;
42 uri_decoder(const string
& uri
):
43 uri(uri
), has_authority(false), has_query(false), has_fragment(false)
46 "^([^:]+):(//[^/?#]*)?([^?#]*)(\\?[^#]*)?(#.*)?$";
48 vector
<string
> matches
;
49 if (regexp_match(uri
, re
, matches
) != 0)
50 throw runtime_error(_F("string doesn't appear to be a URI: %s", uri
.c_str()));
54 if (!matches
[2].empty())
57 authority
= matches
[2].substr(2);
62 if (!matches
[4].empty())
65 query
= matches
[4].substr(1);
68 if (!matches
[5].empty())
71 fragment
= matches
[5].substr(1);
77 // loopback target for running locally
78 class direct
: public remote
{
82 direct(systemtap_session
& s
): remote(s
), child(0) {}
86 args
= make_run_command(*s
);
87 if (! staprun_r_arg
.empty()) // PR13354
89 if (s
->runtime_mode
== systemtap_session::dyninst_runtime
)
90 args
.insert(args
.end(), {"_stp_dyninst_remote=" + staprun_r_arg
});
91 else if (s
->runtime_mode
== systemtap_session::kernel_runtime
)
92 args
.insert(args
.end(), { "-r", staprun_r_arg
});
93 // leave args empty for bpf_runtime
96 pid_t pid
= stap_spawn (s
->verbose
, args
);
108 int ret
= stap_waitpid(s
->verbose
, child
);
110 s
->print_warning(_F("%s exited with signal: %d (%s)",
111 args
.front().c_str(), ret
- 128,
112 strsignal(ret
- 128)));
114 s
->print_warning(_F("%s exited with status: %d",
115 args
.front().c_str(), ret
));
123 virtual ~direct() { finish(); }
127 class stapsh
: public remote
{
132 string remote_version
;
134 string target_stream
;
137 STAPSH_READY
, // ready to receive next command
138 STAPSH_DATA
// currently printing data from a 'data' command
141 virtual void prepare_poll(vector
<pollfd
>& fds
)
143 if (fdout
>= 0 && OUT
)
145 pollfd p
= { fdout
, POLLIN
, 0 };
149 // need to send a signal?
150 if (fdin
>= 0 && IN
&& interrupts_sent
< pending_interrupts
)
152 pollfd p
= { fdin
, POLLOUT
, 0 };
157 virtual void handle_poll(vector
<pollfd
>& fds
)
159 for (unsigned i
=0; i
< fds
.size(); ++i
)
160 if (fds
[i
].fd
== fdin
|| fds
[i
].fd
== fdout
)
164 // need to send a signal?
165 if (fds
[i
].revents
& POLLOUT
&& IN
&&
166 interrupts_sent
< pending_interrupts
)
168 if (send_command("quit\n") == 0)
174 // have data to read?
175 if (fds
[i
].revents
& POLLIN
&& OUT
)
177 // if stapsh doesn't support commands, then just dump everything
178 if (!vector_has(options
, string("data")))
180 // NB: we could splice here, but we don't know how much
181 // data is available for reading. One way could be to
182 // splice in small chunks and poll() fdout to check if
186 while ((bytes_read
= fread(buf
, 1, sizeof(buf
), OUT
)) > 0)
187 printout(buf
, bytes_read
);
191 else // we expect commands (just data for now)
193 // When the 'data' option is turned on, all outputs from
194 // staprun are first prepended with a line formatted as
195 // "data <stream> <size>\n", where <stream> is either
196 // "stdout" or "stderr", and <size> is the size of the
197 // data. Also, the line "quit\n" is sent from stapsh right
200 if (stream_state
== STAPSH_READY
)
204 while ((rc
= fgets(cmdbuf
, sizeof(cmdbuf
), OUT
)) != NULL
)
206 // check if it's a debug output from stapsh itself
207 string line
= string(cmdbuf
);
208 if (startswith(line
, "stapsh:"))
210 else if (startswith(line
, "quit\n"))
211 // && vector_has(options, string("data")))
212 // uncomment above if another command becomes
215 err
= true; // close connection
218 else if (startswith(line
, "data"))
219 // && vector_has(options, string("data")))
220 // uncomment above if another command becomes
224 tokenize(line
, cmd
, " \t\r\n");
225 if (!is_valid_data_cmd(cmd
))
227 clog
<< _("invalid data command from stapsh") << endl
;
228 clog
<< _("received: ") << line
;
233 target_stream
= cmd
[1];
234 data_size
= lex_cast
<size_t>(cmd
[2]);
235 stream_state
= STAPSH_DATA
;
240 if (rc
== NULL
&& errno
!= EAGAIN
)
244 if (stream_state
== STAPSH_DATA
)
248 // keep reading from OUT until either dry or data_size bytes done
250 size_t max_read
= min
<size_t>(sizeof(buf
), data_size
);
251 size_t bytes_read
= 0;
253 && (bytes_read
= fread(buf
, 1, max_read
, OUT
)) > 0)
255 printout(buf
, bytes_read
);
256 data_size
-= bytes_read
;
257 max_read
= min
<size_t>(sizeof(buf
), data_size
);
259 if (bytes_read
== 0 && errno
!= EAGAIN
)
263 stream_state
= STAPSH_READY
;
269 if (err
|| fds
[i
].revents
& ~(POLLIN
|POLLOUT
))
276 // Some schemes like unix may have stdout and stderr mushed together.
277 // There shouldn't be anything except dbug messages on stderr before we
278 // actually start running, and there's no get_reply after that. So
279 // we'll just loop and skip those that start with "stapsh:".
281 while (fgets(reply
, sizeof(reply
), OUT
))
283 if (!startswith(reply
, "stapsh:"))
286 // if data is not prefixed, we will have no way to distinguish
287 // between stdout and stderr during staprun runtime, so we might as
288 // well print to stdout now as well to be more consistent
289 if (vector_has(options
, string("data")))
290 clog
<< reply
; // must be stderr since only replies go to stdout
292 cout
<< reply
; // output to stdout to be more consistent with later
295 // Reached EOF, nothing to reply...
299 int send_command(const string
& cmd
)
303 if (fputs(cmd
.c_str(), IN
) < 0 ||
309 int send_file(const string
& filename
, const string
& dest
)
312 FILE* f
= fopen(filename
.c_str(), "r");
317 rc
= fstat(fileno(f
), &fs
);
321 cmd
<< "file " << fs
.st_size
<< " " << dest
<< "\n";
322 rc
= send_command(cmd
.str());
326 while (!rc
&& i
< fs
.st_size
)
329 size_t r
= sizeof(buf
);
330 if (fs
.st_size
- i
< (off_t
)r
)
332 r
= fread(buf
, 1, r
, f
);
337 size_t w
= fwrite(buf
, 1, r
, IN
);
351 string reply
= get_reply();
358 clog
<< _("stapsh file ERROR: no reply") << endl
;
360 clog
<< _F("stapsh file replied %s", reply
.c_str());
368 static string
qpencode(const string
& str
)
371 o
<< setfill('0') << hex
;
372 for (const char* s
= str
.c_str(); *s
; ++s
)
373 if (*s
>= 33 && *s
<= 126 && *s
!= 61)
376 o
<< '=' << setw(2) << (unsigned)(unsigned char) *s
;
380 static bool is_valid_data_cmd(const vector
<string
>& cmd
)
384 err
= err
|| (cmd
[0] != "data");
385 err
= err
|| (cmd
[1] != "stdout" && cmd
[1] != "stderr");
387 if (!err
) // try to cast as size_t
388 try { lex_cast
<size_t>(cmd
[2]); }
389 catch (...) { err
= true; }
394 virtual void printout(const char *buf
, size_t size
)
396 static string last_prefix
;
397 static bool on_same_line
;
402 // don't prefix for stderr to be more consistent with ssh
403 if (!prefix
.empty() && target_stream
!= "stderr")
405 vector
<pair
<const char*,int> > lines
= split_lines(buf
, size
);
406 for (vector
<pair
<const char*,int> >::iterator it
= lines
.begin();
407 it
!= lines
.end(); ++it
)
409 if (last_prefix
!= prefix
)
415 else if (!on_same_line
)
417 cout
.write(it
->first
, it
->second
);
420 const char *last_line
= lines
.back().first
;
421 const char last_char
= last_line
[lines
.back().second
-1];
422 on_same_line
= !lines
.empty() && last_char
!= '\n';
423 last_prefix
= prefix
;
427 // Otherwise dump the whole block
428 // NB: The buf could contain binary data,
429 // including \0, so write as a block instead of
430 // the usual << string.
431 if (target_stream
== "stdout")
433 cout
.write(buf
, size
);
437 clog
.write(buf
, size
);
442 stapsh(systemtap_session
& s
)
443 : remote(s
), interrupts_sent(0),
444 fdin(-1), fdout(-1), IN(0), OUT(0),
445 data_size(0), target_stream("stdout"), // default to stdout for schemes
446 stream_state(STAPSH_READY
) // that don't pipe stderr (e.g. ssh)
449 vector
<string
> options
;
451 virtual int prepare()
456 if (s
->runtime_mode
== systemtap_session::dyninst_runtime
)
458 else if (s
->runtime_mode
== systemtap_session::bpf_runtime
)
463 string localmodule
= s
->tmpdir
+ "/" + s
->module_name
+ extension
;
464 string remotemodule
= s
->module_name
+ extension
;
466 if ((rc
= send_file(localmodule
, remotemodule
)))
469 if (file_exists(localmodule
+ ".sgn") &&
470 (rc
= send_file(localmodule
+ ".sgn", remotemodule
+ ".sgn")))
473 if (!s
->uprobes_path
.empty())
475 string remoteuprobes
= basename(s
->uprobes_path
.c_str());
476 if ((rc
= send_file(s
->uprobes_path
, remoteuprobes
)))
479 if (file_exists(s
->uprobes_path
+ ".sgn") &&
480 (rc
= send_file(s
->uprobes_path
+ ".sgn", remoteuprobes
+ ".sgn")))
489 // Send the staprun args
490 // NB: The remote is left to decide its own staprun path
491 ostringstream
run("run", ios::out
| ios::ate
);
492 vector
<string
> cmd
= make_run_command(*s
, ".", remote_version
);
494 // PR13354: identify our remote index/url
495 if (strverscmp("1.7", remote_version
.c_str()) <= 0 && // -r supported?
496 ! staprun_r_arg
.empty())
498 if (s
->runtime_mode
== systemtap_session::dyninst_runtime
)
499 cmd
.insert(cmd
.end(), { "_stp_dyninst_remote=" + staprun_r_arg
});
500 else if (s
->runtime_mode
== systemtap_session::kernel_runtime
)
501 cmd
.insert(cmd
.end(), { "-r", staprun_r_arg
});
502 // leave args empty for bpf_runtime
505 for (unsigned i
= 1; i
< cmd
.size(); ++i
)
506 run
<< ' ' << qpencode(cmd
[i
]);
509 int rc
= send_command(run
.str());
513 string reply
= get_reply();
520 clog
<< _("stapsh run ERROR: no reply") << endl
;
522 clog
<< _F("stapsh run replied %s", reply
.c_str());
530 if ((flags
= fcntl(fdout
, F_GETFL
)) == -1
531 || fcntl(fdout
, F_SETFL
, flags
| O_NONBLOCK
) == -1)
533 clog
<< _("failed to change to non-blocking mode") << endl
;
539 // If run failed for any reason, then this
540 // connection is effectively dead to us.
549 if (OUT
) fclose(OUT
);
560 void set_child_fds(int in
, int out
)
562 if (fdin
>= 0 || fdout
>= 0 || IN
|| OUT
)
563 throw runtime_error(_("stapsh file descriptors already set"));
567 IN
= fdopen(fdin
, "w");
568 OUT
= fdopen(fdout
, "r");
570 throw runtime_error(_("invalid file descriptors for stapsh"));
572 if (send_command("stap " VERSION
"\n"))
573 throw runtime_error(_("error sending hello to stapsh"));
575 string reply
= get_reply();
577 throw runtime_error(_("error receiving hello from stapsh"));
579 // stapsh VERSION MACHINE RELEASE
580 vector
<string
> uname
;
581 tokenize(reply
, uname
, " \t\r\n");
582 if (uname
.size() != 4 || uname
[0] != "stapsh")
583 throw runtime_error(_F("invalid hello from stapsh: %s", reply
.c_str()));
585 // We assume that later versions will know how to talk to us.
586 // Looking backward, we use this for make_run_command().
587 this->remote_version
= uname
[1];
589 this->s
= s
->clone(uname
[2], uname
[3]);
591 // set any option requested
592 if (!this->options
.empty())
594 // check first if the option command is supported
595 if (strverscmp("2.4", this->remote_version
.c_str()) > 0)
596 throw runtime_error(_F("stapsh %s does not support options",
597 this->remote_version
.c_str()));
599 for (vector
<string
>::iterator it
= this->options
.begin();
600 it
!= this->options
.end(); ++it
)
602 int rc
= send_command("option " + *it
+ "\n");
604 throw runtime_error(_F("could not set option %s: "
605 "send_command returned %d",
607 string reply
= get_reply();
609 throw runtime_error(_F("could not set option %s: %s",
610 it
->c_str(), reply
.c_str()));
616 virtual ~stapsh() { close(); }
620 // direct_stapsh is meant only for testing, as a way to exercise the stapsh
621 // mechanisms without requiring test machines to have actual remote access.
622 class direct_stapsh
: public stapsh
{
626 direct_stapsh(systemtap_session
& s
)
627 : stapsh(s
), child(0)
630 vector
<string
> cmd
{ BINDIR
"/stapsh" };
631 if (s
.perpass_verbose
[4] > 1)
633 if (s
.perpass_verbose
[4] > 2)
636 // mask signals while we spawn, so we can simulate manual signals to
637 // the "remote" target, as we must for the real ssh_remote case.
639 stap_sigmasker masked
;
640 child
= stap_spawn_piped(s
.verbose
, cmd
, &in
, &out
);
644 throw runtime_error(_("error launching stapsh"));
648 set_child_fds(in
, out
);
650 catch (runtime_error
&)
659 int rc
= stapsh::finish();
663 int rc2
= stap_waitpid(s
->verbose
, child
);
671 virtual ~direct_stapsh() { finish(); }
675 // Connect to an existing stapsh on a unix socket.
676 class unix_stapsh
: public stapsh
{
679 unix_stapsh(systemtap_session
& s
, const uri_decoder
& ud
)
682 // Request that data be encapsulated since both stdout and stderr have
683 // to go over the same line. Also makes stapsh tell us when it quits.
684 this->options
.push_back("data");
686 // set verbosity to the requested level
687 for (unsigned i
= 1; i
< s
.perpass_verbose
[4]; i
++)
688 this->options
.push_back("verbose");
691 server
.sun_family
= AF_UNIX
;
693 throw runtime_error(_("unix target requires a /path"));
694 if (ud
.path
.size() > sizeof(server
.sun_path
) - 1)
695 throw runtime_error(_("unix target /path is too long"));
696 strcpy(server
.sun_path
, ud
.path
.c_str());
698 if (ud
.has_authority
)
699 throw runtime_error(_("unix target doesn't support a hostname"));
701 throw runtime_error(_("unix target URI doesn't support a ?query"));
703 throw runtime_error(_("unix target URI doesn't support a #fragment"));
705 int fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
707 throw runtime_error(_("error opening a socket"));
709 if (connect(fd
, (struct sockaddr
*)&server
, SUN_LEN(&server
)) < 0)
711 const char *msg
= strerror(errno
);
713 throw runtime_error(_F("error connecting to socket %s: %s",
714 server
.sun_path
, msg
));
717 // Try to dup it, so class stapsh can have truly separate fds for its
718 // fdopen handles. If it fails for some reason, it can still work with
726 set_child_fds(fd
, fd2
);
728 catch (runtime_error
&)
740 virtual ~unix_stapsh() { finish(); }
743 class libvirt_stapsh
: public stapsh
{
748 libvirt_stapsh(systemtap_session
& s
, const uri_decoder
& ud
)
754 // Request that data be encapsulated since both stdout and stderr have
755 // to go over the same line. Also makes stapsh tell us when it quits.
756 this->options
.push_back("data");
758 // set verbosity to the requested level
759 for (unsigned i
= 1; i
< s
.perpass_verbose
[4]; i
++)
760 this->options
.push_back("verbose");
762 // A valid libvirt URI has one of two forms:
763 // - libvirt://DOMAIN/LIBVIRT_URI?LIBVIRT_QUERY
764 // - libvirt:DOMAIN/LIBVIRT_URI?LIBVIRT_QUERY
765 // We only advertise the first form, but to be nice, we also accept the
766 // second form. In the first form, DOMAIN is authority, LIBVIRT_URI is
767 // path, and LIBVIRT_QUERY is the query. In the second form, the DOMAIN
768 // is part of the path.
771 throw runtime_error(_("libvirt target URI doesn't support a #fragment"));
773 if (ud
.has_authority
) // first form
775 domain
= ud
.authority
;
776 if (!ud
.path
.empty())
778 libvirt_uri
= ud
.path
.substr(1);
780 libvirt_uri
+= "?" + ud
.query
;
786 throw runtime_error(_("libvirt target URI requires a domain name"));
788 size_t slash
= ud
.path
.find_first_of('/');
789 if (slash
== string::npos
)
793 domain
= ud
.path
.substr(0, slash
);
794 libvirt_uri
= ud
.path
.substr(slash
+1);
800 string stapvirt
= BINDIR
"/stapvirt";
801 if (!file_exists(stapvirt
))
802 throw runtime_error(_("stapvirt missing"));
804 vector
<string
> cmd
{ stapvirt
};
806 // carry verbosity into stapvirt
807 if (s
.perpass_verbose
[4] > 0)
808 cmd
.insert(cmd
.end(), s
.perpass_verbose
[4] - 1, "-v");
810 if (!libvirt_uri
.empty())
811 cmd
.insert(cmd
.end(), { "-c", libvirt_uri
});
813 cmd
.insert(cmd
.end(), { "connect", domain
});
815 // mask signals for stapvirt since it relies instead on stap or stapsh
816 // closing its connection to know when to exit (otherwise, stapvirt
817 // would receive SIGINT on Ctrl-C and exit nonzero)
819 // NB: There is an interesting issue to note here. Some libvirt URIs
820 // will create child processes of stapvirt (e.g. qemu+ssh:// will
821 // create an ssh process under stapvirt, also qemu+ext://, see
822 // <libvirt.org/remote.html> for more info). These processes do not
823 // keep the mask of stapvirt we are creating here, but are still part
824 // of the same process group.
825 // This means that e.g. SIGINT will not be blocked. Thus, stapvirt
826 // explicitly adds a handler for SIGCHLD and forcefully disconnects
827 // upon receiving it (otherwise it would await indefinitely).
829 stap_sigmasker masked
;
830 child
= stap_spawn_piped(s
.verbose
, cmd
, &in
, &out
);
834 throw runtime_error(_("error launching stapvirt"));
838 set_child_fds(in
, out
);
840 catch (runtime_error
&)
849 int rc
= stapsh::finish();
853 int rc2
= stap_waitpid(s
->verbose
, child
);
861 virtual ~libvirt_stapsh() { finish(); }
864 // stapsh-based ssh_remote
865 class ssh_remote
: public stapsh
{
869 ssh_remote(systemtap_session
& s
): stapsh(s
), child(0) {}
871 int connect(const string
& host
, const string
& port
)
875 vector
<string
> cmd
{ "ssh", "-q", host
};
877 cmd
.insert(cmd
.end(), { "-p", port
});
879 // This is crafted so that we get a silent failure with status 127 if
880 // the command is not found. The combination of -P and $cmd ensures
881 // that we pull the command out of the PATH, not aliases or such.
882 string stapsh_cmd
= "cmd=`type -P stapsh || exit 127` && exec \"$cmd\"";
883 if (s
->perpass_verbose
[4] > 1)
884 stapsh_cmd
.append(" -v");
885 if (s
->perpass_verbose
[4] > 2)
886 stapsh_cmd
.append(" -v");
887 // NB: We need to explicitly choose bash, as $SHELL may be weird...
888 cmd
.push_back("/bin/bash -c '" + stapsh_cmd
+ "'");
890 // mask signals while we spawn, so we can manually send even tty
891 // signals *through* ssh rather than to ssh itself
893 stap_sigmasker masked
;
894 child
= stap_spawn_piped(s
->verbose
, cmd
, &in
, &out
);
898 throw runtime_error(_("error launching stapsh"));
902 set_child_fds(in
, out
);
904 catch (runtime_error
&)
908 // ssh itself signals errors with 255
910 throw runtime_error(_("error establishing ssh connection"));
912 // If rc == 127, that's command-not-found, so we let ::create()
913 // try again in legacy mode. But only do this if there's a single
914 // remote, as the old code didn't handle ttys well with multiple
915 // remotes. Otherwise, throw up again. *barf*
916 if (rc
!= 127 || s
->remote_uris
.size() > 1)
925 int rc
= stapsh::finish();
929 int rc2
= stap_waitpid(s
->verbose
, child
);
936 static remote
* create(systemtap_session
& s
, const string
& host
);
937 static remote
* create(systemtap_session
& s
, const uri_decoder
& ud
);
939 virtual ~ssh_remote() { finish(); }
943 // ssh connection without stapsh, for legacy stap installations
944 // NB: ssh commands use a tty (-t) so signals are passed along to the remote.
945 // It does this by putting the local tty in raw mode, so it only works for tty
946 // signals, and only for a single remote at a time.
947 class ssh_legacy_remote
: public remote
{
949 vector
<string
> ssh_args
, scp_args
;
951 string host
, port
, tmpdir
;
954 ssh_legacy_remote(systemtap_session
& s
, const string
& host
, const string
& port
)
955 : remote(s
), host(host
), port(port
), child(0)
957 open_control_master();
962 catch (runtime_error
&)
964 close_control_master();
969 vector
<string
> ssh_command(initializer_list
<string
> ilist
)
971 vector
<string
> cmd
= ssh_args
;
972 cmd
.insert(cmd
.end(), ilist
);
976 int copy_to_remote(const string
& local
, const string
& remote
)
978 vector
<string
> cmd
= scp_args
;
979 cmd
.insert(cmd
.end(), { local
, host
+ ":" + remote
});
980 return stap_system(s
->verbose
, cmd
);
983 void open_control_master()
985 static unsigned index
= 0;
987 if (s
->tmpdir
.empty()) // sanity check, shouldn't happen
988 throw runtime_error(_("No tmpdir available for ssh control master"));
990 ssh_control
= s
->tmpdir
+ "/ssh_remote_control_" + lex_cast(++index
);
992 scp_args
= { "scp", "-q", "-o", "ControlPath=" + ssh_control
};
993 ssh_args
= { "ssh", "-q", "-o", "ControlPath=" + ssh_control
, host
};
997 scp_args
.insert(scp_args
.end(), { "-P", port
});
998 ssh_args
.insert(ssh_args
.end(), { "-p", port
});
1001 // NB: ssh -f will stay in the foreground until authentication is
1002 // complete and the control socket is created, so we know it's ready to
1003 // go when stap_system returns.
1004 auto cmd
= ssh_command({ "-f", "-N", "-M" });
1005 int rc
= stap_system(s
->verbose
, cmd
);
1007 throw runtime_error(_F("failed to create an ssh control master for %s : rc= %d",
1011 clog
<< _F("Created ssh control master at %s",
1012 lex_cast_qstring(ssh_control
).c_str()) << endl
;
1015 void close_control_master()
1017 if (ssh_control
.empty())
1020 auto cmd
= ssh_command({ "-O", "exit" });
1021 int rc
= stap_system(s
->verbose
, cmd
, true, true);
1023 cerr
<< _F("failed to stop the ssh control master for %s : rc=%d",
1024 host
.c_str(), rc
) << endl
;
1026 ssh_control
.clear();
1034 vector
<string
> uname
;
1035 auto cmd
= ssh_command({ "-t", "uname -rm" });
1036 int rc
= stap_system_read(s
->verbose
, cmd
, out
);
1038 tokenize(out
.str(), uname
, " \t\r\n");
1039 if (uname
.size() != 2)
1040 throw runtime_error(_F("failed to get uname from %s : rc= %d", host
.c_str(), rc
));
1041 const string
& release
= uname
[0];
1042 const string
& arch
= uname
[1];
1043 // XXX need to deal with command-line vs. implied arch/release
1044 this->s
= s
->clone(arch
, release
);
1050 string localmodule
= s
->tmpdir
+ "/" + s
->module_name
+ ".ko";
1053 // Make a remote tempdir.
1056 vector
<string
> vout
;
1057 auto cmd
= ssh_command({ "-t", "mktemp -d -t stapXXXXXX" });
1058 rc
= stap_system_read(s
->verbose
, cmd
, out
);
1060 tokenize(out
.str(), vout
, "\r\n");
1061 if (vout
.size() != 1)
1063 cerr
<< _F("failed to make a tempdir on %s : rc=%d",
1064 host
.c_str(), rc
) << endl
;
1068 tmpmodule
= tmpdir
+ "/" + s
->module_name
+ ".ko";
1071 // Transfer the module.
1074 rc
= copy_to_remote(localmodule
, tmpmodule
);
1076 cerr
<< _F("failed to copy the module to %s : rc=%d",
1077 host
.c_str(), rc
) << endl
;
1080 // Transfer the module signature.
1081 if (rc
== 0 && file_exists(localmodule
+ ".sgn"))
1083 rc
= copy_to_remote(localmodule
+ ".sgn", tmpmodule
+ ".sgn");
1085 cerr
<< _F("failed to copy the module signature to %s : rc=%d",
1086 host
.c_str(), rc
) << endl
;
1089 // What about transfering uprobes.ko? In this ssh "legacy" mode, we
1090 // don't the remote systemtap version, but -uPATH wasn't added until
1091 // 1.4. Rather than risking a getopt error, we'll just assume that
1092 // this isn't supported. The remote will just have to provide its own
1093 // uprobes.ko in SYSTEMTAP_RUNTIME or already loaded.
1095 // Run the module on the remote.
1097 // We don't know the actual version, but all <=1.3 are approx equal.
1098 vector
<string
> staprun_cmd
= make_run_command(*s
, tmpdir
, "1.3");
1099 staprun_cmd
[0] = "staprun"; // NB: The remote decides its own path
1100 // NB: PR13354: we assume legacy installations don't have
1101 // staprun -r support, so we ignore staprun_r_arg.
1102 auto cmd
= ssh_command({ "-t", cmdstr_join(staprun_cmd
) });
1103 pid_t pid
= stap_spawn(s
->verbose
, cmd
);
1108 cerr
<< _F("failed to run the module on %s : ret=%d",
1109 host
.c_str(), pid
) << endl
;
1123 rc
= stap_waitpid(s
->verbose
, child
);
1127 if (!tmpdir
.empty())
1129 // Remove the tempdir.
1130 // XXX need to make sure this runs even with e.g. CTRL-C exits
1131 auto cmd
= ssh_command({ "-t", "rm -r " + cmdstr_quoted(tmpdir
) });
1132 int rc2
= stap_system(s
->verbose
, cmd
);
1134 cerr
<< _F("failed to delete the tempdir on %s : rc=%d",
1135 host
.c_str(), rc2
) << endl
;
1141 close_control_master();
1147 friend class ssh_remote
;
1149 virtual ~ssh_legacy_remote()
1151 close_control_master();
1156 // Try to establish a stapsh connection to the remote, but fallback
1157 // to the older mechanism if the command is not found.
1159 ssh_remote::create(systemtap_session
& s
, const string
& target
)
1161 string port
, host
= target
;
1162 size_t i
= host
.find(':');
1163 if (i
!= string::npos
)
1165 port
= host
.substr(i
+ 1);
1169 unique_ptr
<ssh_remote
> p (new ssh_remote(s
));
1170 int rc
= p
->connect(host
, port
);
1173 else if (rc
== 127) // stapsh command not found
1174 return new ssh_legacy_remote(s
, host
, port
); // try legacy instead
1179 ssh_remote::create(systemtap_session
& s
, const uri_decoder
& ud
)
1181 if (!ud
.has_authority
|| ud
.authority
.empty())
1182 throw runtime_error(_("ssh target requires a hostname"));
1183 if (!ud
.path
.empty() && ud
.path
!= "/")
1184 throw runtime_error(_("ssh target URI doesn't support a /path"));
1186 throw runtime_error(_("ssh target URI doesn't support a ?query"));
1187 if (ud
.has_fragment
)
1188 throw runtime_error(_("ssh target URI doesn't support a #fragment"));
1190 return create(s
, ud
.authority
);
1195 remote::create(systemtap_session
& s
, const string
& uri
, int idx
)
1200 if (uri
.find(':') != string::npos
)
1202 const uri_decoder
ud(uri
);
1204 // An ssh "host:port" is ambiguous with a URI "scheme:path".
1205 // So if it looks like a number, just assume ssh.
1206 if (!ud
.has_authority
&& !ud
.has_query
&&
1207 !ud
.has_fragment
&& !ud
.path
.empty() &&
1208 ud
.path
.find_first_not_of("1234567890") == string::npos
)
1209 it
= ssh_remote::create(s
, uri
);
1210 else if (ud
.scheme
== "direct")
1212 else if (ud
.scheme
== "stapsh")
1213 it
= new direct_stapsh(s
);
1214 else if (ud
.scheme
== "unix")
1215 it
= new unix_stapsh(s
, ud
);
1216 else if (ud
.scheme
== "libvirt")
1217 it
= new libvirt_stapsh(s
, ud
);
1218 else if (ud
.scheme
== "ssh")
1219 it
= ssh_remote::create(s
, ud
);
1221 throw runtime_error(_F("unrecognized URI scheme '%s' in remote: %s",
1222 ud
.scheme
.c_str(), uri
.c_str()));
1225 // XXX assuming everything else is ssh for now...
1226 it
= ssh_remote::create(s
, uri
);
1228 catch (std::runtime_error
& e
)
1230 cerr
<< e
.what() << " on remote '" << uri
<< "'" << endl
;
1234 if (it
&& idx
>= 0) // PR13354: remote metadata for staprun -r IDX:URI
1237 r_arg
<< idx
<< ":" << uri
;
1238 it
->staprun_r_arg
= r_arg
.str();
1245 remote::run(const vector
<remote
*>& remotes
)
1247 // NB: the first failure "wins"
1248 int ret
= 0, rc
= 0;
1250 for (unsigned i
= 0; i
< remotes
.size() && !pending_interrupts
; ++i
)
1252 remote
*r
= remotes
[i
];
1253 r
->s
->verbose
= r
->s
->perpass_verbose
[4];
1254 if (r
->s
->use_remote_prefix
)
1255 r
->prefix
= lex_cast(i
) + ": ";
1261 for (unsigned i
= 0; i
< remotes
.size() && !pending_interrupts
; ++i
)
1263 rc
= remotes
[i
]->start();
1268 // mask signals while we're preparing to poll
1270 stap_sigmasker masked
;
1272 // polling loop for remotes that have fds to watch
1276 for (unsigned i
= 0; i
< remotes
.size(); ++i
)
1277 remotes
[i
]->prepare_poll (fds
);
1281 rc
= ppoll (&fds
[0], fds
.size(), NULL
, &masked
.old
);
1282 if (rc
< 0 && errno
!= EINTR
)
1285 for (unsigned i
= 0; i
< remotes
.size(); ++i
)
1286 remotes
[i
]->handle_poll (fds
);
1290 for (unsigned i
= 0; i
< remotes
.size(); ++i
)
1292 rc
= remotes
[i
]->finish();
1301 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.093847 seconds and 5 git commands to generate.