]> sourceware.org Git - systemtap.git/blob - remote.cxx
PR12115: Give remote-ssh a tty, and quiet status messages
[systemtap.git] / remote.cxx
1 // systemtap remote execution
2 // Copyright (C) 2010 Red Hat Inc.
3 //
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
7 // later version.
8
9 extern "C" {
10 #include <sys/utsname.h>
11 }
12
13 #include <stdexcept>
14 #include <sstream>
15 #include <string>
16 #include <vector>
17
18 #include "buildrun.h"
19 #include "remote.h"
20 #include "util.h"
21
22 using namespace std;
23
24 // loopback target for running locally
25 class direct : public remote {
26 protected:
27 direct(systemtap_session& s)
28 {
29 struct utsname buf;
30 (void) uname (& buf);
31 arch = normalize_machine(buf.machine);
32 release = buf.release;
33 }
34
35 public:
36 friend class remote;
37 int run(systemtap_session& s) {
38 string module = s.tmpdir + "/" + s.module_name + ".ko";
39 return stap_system (s.verbose, make_run_command (s, module));
40 }
41 };
42
43 class ssh_remote : public remote {
44 // NB: ssh commands use a tty (-t) so signals are passed along to the remote
45 private:
46 string uri;
47 ssh_remote(systemtap_session& s, const string& uri): uri(uri)
48 {
49 ostringstream out;
50 vector<string> uname;
51 string uname_cmd = "ssh -t -q " + lex_cast_qstring(uri) + " uname -rm";
52 int rc = stap_system_read(s.verbose, uname_cmd, out);
53 if (rc == 0)
54 tokenize(out.str(), uname, " \t\r\n");
55 if (uname.size() != 2)
56 throw runtime_error("failed to get uname from " + uri
57 + " : rc=" + lex_cast(rc));
58 release = uname[0];
59 arch = uname[1];
60 }
61
62 public:
63 friend class remote;
64 int run(systemtap_session& s)
65 {
66 int rc;
67 string localmodule = s.tmpdir + "/" + s.module_name + ".ko";
68 string tmpdir, tmpmodule;
69 string quri = lex_cast_qstring(uri);
70
71 // Make a remote tempdir.
72 {
73 ostringstream out;
74 vector<string> vout;
75 string cmd = "ssh -t -q " + quri + " mktemp -d -t stapXXXXXX";
76 rc = stap_system_read(s.verbose, cmd, out);
77 if (rc == 0)
78 tokenize(out.str(), vout, "\r\n");
79 if (vout.size() != 1)
80 {
81 cerr << "failed to make a tempdir on " << uri
82 << " : rc=" << rc << endl;
83 return -1;
84 }
85 tmpdir = vout[0];
86 tmpmodule = tmpdir + "/" + s.module_name + ".ko";
87 }
88
89 // Transfer the module. XXX and uprobes.ko, sigs, etc.
90 if (rc == 0) {
91 string cmd = "scp -q " + localmodule + " " + quri + ":" + tmpmodule;
92 rc = stap_system(s.verbose, cmd);
93 if (rc != 0)
94 cerr << "failed to copy the module to " << uri
95 << " : rc=" << rc << endl;
96 }
97
98 // Run the module on the remote.
99 if (rc == 0) {
100 string cmd = "ssh -t -q " + quri + " "
101 + lex_cast_qstring(make_run_command(s, tmpmodule));
102 rc = stap_system(s.verbose, cmd);
103 if (rc != 0)
104 cerr << "failed to run the module on " << uri
105 << " : rc=" << rc << endl;
106 }
107
108 // Remove the tempdir.
109 // XXX need to make sure this runs even with e.g. CTRL-C exits
110 {
111 string cmd = "ssh -t -q " + quri + " rm -r " + tmpdir;
112 int rc2 = stap_system(s.verbose, cmd);
113 if (rc2 != 0)
114 cerr << "failed to delete the tempdir on " << uri
115 << " : rc=" << rc2 << endl;
116 if (rc == 0)
117 rc = rc2;
118 }
119
120 return rc;
121 }
122 };
123
124
125 remote*
126 remote::create(systemtap_session& s, const string& uri)
127 {
128 try
129 {
130 if (uri == "direct")
131 return new direct(s);
132 else
133 // XXX assuming everything else is ssh for now...
134 return new ssh_remote(s, uri);
135 }
136 catch (std::runtime_error& e)
137 {
138 cerr << e.what() << endl;
139 return NULL;
140 }
141 }
142
143
144 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.04449 seconds and 6 git commands to generate.