libssh 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +1 -0
- data/example/exec.rb +7 -19
- data/example/local_forward.rb +65 -0
- data/example/sshkit.rb +2 -0
- data/ext/libssh_ruby/channel.c +163 -41
- data/ext/libssh_ruby/extconf.rb +15 -3
- data/ext/libssh_ruby/libssh_ruby.c +4 -0
- data/lib/libssh/version.rb +1 -1
- data/lib/sshkit/backends/libssh.rb +34 -44
- data/libssh.gemspec +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4aaa6647d6cc89439be59eeacbf35a3a21d72bf5
|
4
|
+
data.tar.gz: fe1ea02bf8d3405739187fddcfa2064486d5db98
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ded180b1cfe0766e45e2ddefd438db49c9ca8c2a4edf2dde1fe59453274010df4d7c3a9f038224d35345285d22a6c3b7a7836b1ffb6601119ce2aa3cb464c94a
|
7
|
+
data.tar.gz: 7b6fda7559baeeabe109e7ac30222335d52d930f752ae4542d51a81351d5e08e444fb48ad41826616d0b298dea8c67415e9d99f2c11b2a48d19c5e09d7a2e690
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -38,6 +38,7 @@ See [example](example) directory.
|
|
38
38
|
See [example/sshkit.rb](example/sshkit.rb) .
|
39
39
|
|
40
40
|
### With Capistrano
|
41
|
+
sshkit must be v1.9.0 or later due to [SSHKit::Backend::ConnectionPool API change](https://github.com/capistrano/sshkit/releases/tag/v1.9.0.rc1).
|
41
42
|
|
42
43
|
```ruby
|
43
44
|
require 'sshkit/backends/libssh'
|
data/example/exec.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'libssh'
|
3
|
-
require 'io/wait'
|
4
3
|
|
5
4
|
GC.stress = true
|
6
5
|
puts "libssh #{LibSSH::LIBSSH_VERSION}"
|
@@ -39,28 +38,17 @@ end
|
|
39
38
|
bufsiz = 16384
|
40
39
|
|
41
40
|
channel = LibSSH::Channel.new(session)
|
42
|
-
io = IO.for_fd(session.fd, autoclose: false)
|
43
41
|
channel.open_session do
|
44
42
|
channel.request_exec('ps auxf')
|
45
43
|
until channel.eof?
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
if out && !out.empty?
|
51
|
-
$stdout.write(out)
|
52
|
-
else
|
53
|
-
break
|
54
|
-
end
|
44
|
+
LibSSH::Channel.select([channel], [], [], nil)
|
45
|
+
out = channel.read_nonblocking(bufsiz)
|
46
|
+
if out && !out.empty?
|
47
|
+
$stdout.write(out)
|
55
48
|
end
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
if err && !err.empty?
|
60
|
-
$stderr.write(err)
|
61
|
-
else
|
62
|
-
break
|
63
|
-
end
|
49
|
+
err = channel.read_nonblocking(bufsiz, stderr: true)
|
50
|
+
if err && !err.empty?
|
51
|
+
$stderr.write(err)
|
64
52
|
end
|
65
53
|
end
|
66
54
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'libssh'
|
3
|
+
require 'socket'
|
4
|
+
require 'thread'
|
5
|
+
|
6
|
+
GC.stress = true
|
7
|
+
|
8
|
+
ssh_host = 'rossmann'
|
9
|
+
remote_host = 'localhost'
|
10
|
+
remote_port = 5432
|
11
|
+
local_port = 3000
|
12
|
+
|
13
|
+
session = LibSSH::Session.new
|
14
|
+
session.host = ssh_host
|
15
|
+
session.parse_config
|
16
|
+
session.add_identity('%d/id_ed25519')
|
17
|
+
|
18
|
+
session.connect
|
19
|
+
if session.server_known != LibSSH::SERVER_KNOWN_OK
|
20
|
+
raise 'server unknown'
|
21
|
+
end
|
22
|
+
if session.userauth_publickey_auto != LibSSH::AUTH_SUCCESS
|
23
|
+
raise 'authorization failed'
|
24
|
+
end
|
25
|
+
|
26
|
+
mutex = Mutex.new
|
27
|
+
cv = ConditionVariable.new
|
28
|
+
server_thread = Thread.start do
|
29
|
+
bufsiz = 16384
|
30
|
+
TCPServer.open(local_port) do |server|
|
31
|
+
mutex.synchronize { cv.signal }
|
32
|
+
socket = server.accept
|
33
|
+
channel = LibSSH::Channel.new(session)
|
34
|
+
channel.open_forward(remote_host, remote_port) do
|
35
|
+
reader = Thread.start do
|
36
|
+
begin
|
37
|
+
loop do
|
38
|
+
channel.write(socket.readpartial(bufsiz))
|
39
|
+
end
|
40
|
+
# rubocop:disable Lint/HandleExceptions
|
41
|
+
rescue EOFError
|
42
|
+
end
|
43
|
+
channel.send_eof
|
44
|
+
end
|
45
|
+
|
46
|
+
writer = Thread.start do
|
47
|
+
loop do
|
48
|
+
size = channel.poll
|
49
|
+
if size.nil?
|
50
|
+
break
|
51
|
+
end
|
52
|
+
data = channel.read(size)
|
53
|
+
socket.write(data)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
reader.join
|
58
|
+
writer.join
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
mutex.synchronize { cv.wait(mutex) }
|
64
|
+
system('psql', '-h', 'localhost', '-p', local_port.to_s, '-U', 'postgres', '-d', 'postgres', '-c', 'SELECT NOW()')
|
65
|
+
server_thread.join
|
data/example/sshkit.rb
CHANGED
data/ext/libssh_ruby/channel.c
CHANGED
@@ -105,34 +105,14 @@ static VALUE m_close(VALUE self) {
|
|
105
105
|
return Qnil;
|
106
106
|
}
|
107
107
|
|
108
|
-
static void select_session(ssh_session session) {
|
109
|
-
fd_set fds;
|
110
|
-
int fd;
|
111
|
-
|
112
|
-
FD_ZERO(&fds);
|
113
|
-
fd = ssh_get_fd(session);
|
114
|
-
FD_SET(fd, &fds);
|
115
|
-
select(fd + 1, &fds, NULL, NULL, NULL);
|
116
|
-
}
|
117
|
-
|
118
108
|
static void *nogvl_open_session(void *ptr) {
|
119
109
|
struct nogvl_channel_args *args = ptr;
|
120
|
-
|
121
|
-
int blocking = ssh_is_blocking(session);
|
122
|
-
|
123
|
-
ssh_set_blocking(session, 0);
|
124
|
-
while (1) {
|
125
|
-
args->rc = ssh_channel_open_session(args->channel);
|
126
|
-
if (args->rc != SSH_AGAIN) {
|
127
|
-
break;
|
128
|
-
}
|
129
|
-
rb_thread_check_ints();
|
130
|
-
select_session(session);
|
131
|
-
}
|
132
|
-
ssh_set_blocking(session, blocking);
|
110
|
+
args->rc = ssh_channel_open_session(args->channel);
|
133
111
|
return NULL;
|
134
112
|
}
|
135
113
|
|
114
|
+
/* FIXME: When Channel#open_session is called before authorization,
|
115
|
+
* #open_session will block infinitely and unable to stop it by C-c. */
|
136
116
|
/*
|
137
117
|
* @overload open_session
|
138
118
|
* Open a session channel, and close it after the block.
|
@@ -162,6 +142,51 @@ static VALUE m_open_session(VALUE self) {
|
|
162
142
|
}
|
163
143
|
}
|
164
144
|
|
145
|
+
struct nogvl_open_forward_args {
|
146
|
+
ssh_channel channel;
|
147
|
+
const char *remote_host;
|
148
|
+
int remote_port;
|
149
|
+
int rc;
|
150
|
+
};
|
151
|
+
|
152
|
+
static void *nogvl_open_forward(void *ptr) {
|
153
|
+
struct nogvl_open_forward_args *args = ptr;
|
154
|
+
args->rc = ssh_channel_open_forward(args->channel, args->remote_host,
|
155
|
+
args->remote_port, "localhost", 22);
|
156
|
+
return NULL;
|
157
|
+
}
|
158
|
+
|
159
|
+
/* FIXME: When Channel#open_forward is called before authorization,
|
160
|
+
* #open_session will block infinitely and unable to stop it by C-c. */
|
161
|
+
/*
|
162
|
+
* @overload open_forward(remote_host, remote_port)
|
163
|
+
* Open a TCP/IP forwarding channel.
|
164
|
+
* @param [String] remote_host The remote host to connected.
|
165
|
+
* @param [Fixnum] remote_port The remote port.
|
166
|
+
* @return [nil]
|
167
|
+
* @since 0.4.0
|
168
|
+
* @see http://api.libssh.org/stable/group__libssh__channel.html
|
169
|
+
* ssh_channel_open_forward
|
170
|
+
*/
|
171
|
+
static VALUE m_open_forward(VALUE self, VALUE remote_host, VALUE remote_port) {
|
172
|
+
ChannelHolder *holder;
|
173
|
+
struct nogvl_open_forward_args args;
|
174
|
+
|
175
|
+
TypedData_Get_Struct(self, ChannelHolder, &channel_type, holder);
|
176
|
+
args.remote_host = StringValueCStr(remote_host);
|
177
|
+
Check_Type(remote_port, T_FIXNUM);
|
178
|
+
args.remote_port = FIX2INT(remote_port);
|
179
|
+
args.channel = holder->channel;
|
180
|
+
rb_thread_call_without_gvl(nogvl_open_forward, &args, RUBY_UBF_IO, NULL);
|
181
|
+
RAISE_IF_ERROR(args.rc);
|
182
|
+
|
183
|
+
if (rb_block_given_p()) {
|
184
|
+
return rb_ensure(rb_yield, Qnil, m_close, self);
|
185
|
+
} else {
|
186
|
+
return Qnil;
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
165
190
|
struct nogvl_request_exec_args {
|
166
191
|
ssh_channel channel;
|
167
192
|
char *cmd;
|
@@ -236,10 +261,10 @@ static void *nogvl_read(void *ptr) {
|
|
236
261
|
}
|
237
262
|
|
238
263
|
/*
|
239
|
-
* @overload read(count,
|
264
|
+
* @overload read(count, stderr: false, timeout: -1)
|
240
265
|
* Read data from a channel.
|
241
266
|
* @param [Fixnum] count The count of bytes to be read.
|
242
|
-
* @param [Boolean]
|
267
|
+
* @param [Boolean] stderr Read from the stderr flow or not.
|
243
268
|
* @param [Fixnum] timeout A timeout in seconds. +-1+ means infinite timeout.
|
244
269
|
* @return [String] Data read from the channel.
|
245
270
|
* @see http://api.libssh.org/stable/group__libssh__channel.html
|
@@ -333,7 +358,7 @@ static VALUE m_read_nonblocking(int argc, VALUE *argv, VALUE self) {
|
|
333
358
|
|
334
359
|
/*
|
335
360
|
* @overload eof?
|
336
|
-
* Check if remote
|
361
|
+
* Check if remote has sent an EOF.
|
337
362
|
* @return [Boolean]
|
338
363
|
* @see http://api.libssh.org/stable/group__libssh__channel.html
|
339
364
|
* ssh_channel_is_eof
|
@@ -345,6 +370,36 @@ static VALUE m_eof_p(VALUE self) {
|
|
345
370
|
return ssh_channel_is_eof(holder->channel) ? Qtrue : Qfalse;
|
346
371
|
}
|
347
372
|
|
373
|
+
/*
|
374
|
+
* @overload closed?
|
375
|
+
* Check if the channel is closed or not.
|
376
|
+
* @return [Boolean]
|
377
|
+
* @since 0.4.0
|
378
|
+
* @see http://api.libssh.org/stable/group__libssh__channel.html
|
379
|
+
* ssh_channel_is_closed
|
380
|
+
*/
|
381
|
+
static VALUE m_closed_p(VALUE self) {
|
382
|
+
ChannelHolder *holder;
|
383
|
+
|
384
|
+
TypedData_Get_Struct(self, ChannelHolder, &channel_type, holder);
|
385
|
+
return ssh_channel_is_closed(holder->channel) ? Qtrue : Qfalse;
|
386
|
+
}
|
387
|
+
|
388
|
+
/*
|
389
|
+
* @overload open?
|
390
|
+
* Check if the channel is open or not.
|
391
|
+
* @return [Boolean]
|
392
|
+
* @since 0.4.0
|
393
|
+
* @see http://api.libssh.org/stable/group__libssh__channel.html
|
394
|
+
* ssh_channel_is_open
|
395
|
+
*/
|
396
|
+
static VALUE m_open_p(VALUE self) {
|
397
|
+
ChannelHolder *holder;
|
398
|
+
|
399
|
+
TypedData_Get_Struct(self, ChannelHolder, &channel_type, holder);
|
400
|
+
return ssh_channel_is_open(holder->channel) ? Qtrue : Qfalse;
|
401
|
+
}
|
402
|
+
|
348
403
|
struct nogvl_poll_args {
|
349
404
|
ssh_channel channel;
|
350
405
|
int timeout;
|
@@ -360,9 +415,9 @@ static void *nogvl_poll(void *ptr) {
|
|
360
415
|
}
|
361
416
|
|
362
417
|
/*
|
363
|
-
* @overload poll(
|
418
|
+
* @overload poll(stderr: false, timeout: -1)
|
364
419
|
* Poll a channel for data to read.
|
365
|
-
* @param [Boolean]
|
420
|
+
* @param [Boolean] stderr A boolean to select the stderr stream.
|
366
421
|
* @param [Fixnum] timeout A timeout in milliseconds. A negative value means an
|
367
422
|
* infinite timeout.
|
368
423
|
* @return [Fixnum, nil] The number of bytes available for reading. +nil+ if
|
@@ -405,22 +460,12 @@ static VALUE m_poll(int argc, VALUE *argv, VALUE self) {
|
|
405
460
|
|
406
461
|
static void *nogvl_get_exit_status(void *ptr) {
|
407
462
|
struct nogvl_channel_args *args = ptr;
|
408
|
-
|
409
|
-
int blocking = ssh_is_blocking(session);
|
410
|
-
|
411
|
-
ssh_set_blocking(session, 0);
|
412
|
-
while (1) {
|
413
|
-
args->rc = ssh_channel_get_exit_status(args->channel);
|
414
|
-
if (args->rc != SSH_ERROR) {
|
415
|
-
break;
|
416
|
-
}
|
417
|
-
rb_thread_check_ints();
|
418
|
-
select_session(session);
|
419
|
-
}
|
420
|
-
ssh_set_blocking(session, blocking);
|
463
|
+
args->rc = ssh_channel_get_exit_status(args->channel);
|
421
464
|
return NULL;
|
422
465
|
}
|
423
466
|
|
467
|
+
/* FIXME: When Channel#get_exit_status is called before #request_exec,
|
468
|
+
* #get_exit_status will block infinitely and unable to stop it by C-c. */
|
424
469
|
/*
|
425
470
|
* @overload get_exit_status
|
426
471
|
* Get the exit status of the channel.
|
@@ -502,6 +547,76 @@ static VALUE m_send_eof(VALUE self) {
|
|
502
547
|
return Qnil;
|
503
548
|
}
|
504
549
|
|
550
|
+
struct nogvl_select_args {
|
551
|
+
ssh_channel *read_channels, *write_channels, *except_channels;
|
552
|
+
struct timeval *timeout;
|
553
|
+
int rc;
|
554
|
+
};
|
555
|
+
|
556
|
+
static void *nogvl_select(void *ptr) {
|
557
|
+
struct nogvl_select_args *args = ptr;
|
558
|
+
args->rc = ssh_channel_select(args->read_channels, args->write_channels,
|
559
|
+
args->except_channels, args->timeout);
|
560
|
+
return NULL;
|
561
|
+
}
|
562
|
+
|
563
|
+
static void set_select_channels(ssh_channel **c_channels, VALUE rb_channels) {
|
564
|
+
long i, len;
|
565
|
+
|
566
|
+
Check_Type(rb_channels, T_ARRAY);
|
567
|
+
len = RARRAY_LEN(rb_channels);
|
568
|
+
if (len == 0) {
|
569
|
+
*c_channels = NULL;
|
570
|
+
} else {
|
571
|
+
for (i = 0; i < len; i++) {
|
572
|
+
Check_TypedStruct(RARRAY_AREF(rb_channels, i), &channel_type);
|
573
|
+
}
|
574
|
+
*c_channels = ALLOC_N(ssh_channel, len+1);
|
575
|
+
for (i = 0; i < len; i++) {
|
576
|
+
ChannelHolder *holder;
|
577
|
+
TypedData_Get_Struct(RARRAY_AREF(rb_channels, i), ChannelHolder,
|
578
|
+
&channel_type, holder);
|
579
|
+
(*c_channels)[i] = holder->channel;
|
580
|
+
}
|
581
|
+
(*c_channels)[len] = NULL;
|
582
|
+
}
|
583
|
+
}
|
584
|
+
|
585
|
+
/*
|
586
|
+
* @overload select(read_channels, write_channels, except_channels, timeout)
|
587
|
+
* Act like the standard select(2) on channels.
|
588
|
+
* @param [Array<Channel>] read_channels
|
589
|
+
* @param [Array<Channel>] write_channels
|
590
|
+
* @param [Array<Channel>] except_channels
|
591
|
+
* @param [Fixnum, nil] timeout timeout in seconds.
|
592
|
+
* @return [nil]
|
593
|
+
* @see http://api.libssh.org/stable/group__libssh__channel.html
|
594
|
+
* ssh_channel_select
|
595
|
+
*/
|
596
|
+
static VALUE s_select(RB_UNUSED_VAR(VALUE self), VALUE read_channels,
|
597
|
+
VALUE write_channels, VALUE except_channels,
|
598
|
+
VALUE timeout) {
|
599
|
+
struct nogvl_select_args args;
|
600
|
+
struct timeval tv;
|
601
|
+
|
602
|
+
if (NIL_P(timeout)) {
|
603
|
+
args.timeout = NULL;
|
604
|
+
} else {
|
605
|
+
Check_Type(timeout, T_FIXNUM);
|
606
|
+
tv.tv_sec = FIX2INT(timeout);
|
607
|
+
tv.tv_usec = 0;
|
608
|
+
args.timeout = &tv;
|
609
|
+
}
|
610
|
+
set_select_channels(&args.read_channels, read_channels);
|
611
|
+
set_select_channels(&args.write_channels, write_channels);
|
612
|
+
set_select_channels(&args.except_channels, except_channels);
|
613
|
+
rb_thread_call_without_gvl(nogvl_select, &args, RUBY_UBF_IO, NULL);
|
614
|
+
ruby_xfree(args.read_channels);
|
615
|
+
ruby_xfree(args.write_channels);
|
616
|
+
ruby_xfree(args.except_channels);
|
617
|
+
return Qnil;
|
618
|
+
}
|
619
|
+
|
505
620
|
/*
|
506
621
|
* Document-class: LibSSH::Channel
|
507
622
|
* Wrapper for ssh_channel struct in libssh.
|
@@ -518,6 +633,8 @@ void Init_libssh_channel(void) {
|
|
518
633
|
RUBY_METHOD_FUNC(m_initialize), 1);
|
519
634
|
rb_define_method(rb_cLibSSHChannel, "open_session",
|
520
635
|
RUBY_METHOD_FUNC(m_open_session), 0);
|
636
|
+
rb_define_method(rb_cLibSSHChannel, "open_forward",
|
637
|
+
RUBY_METHOD_FUNC(m_open_forward), 2);
|
521
638
|
rb_define_method(rb_cLibSSHChannel, "close", RUBY_METHOD_FUNC(m_close), 0);
|
522
639
|
rb_define_method(rb_cLibSSHChannel, "request_exec",
|
523
640
|
RUBY_METHOD_FUNC(m_request_exec), 1);
|
@@ -528,12 +645,17 @@ void Init_libssh_channel(void) {
|
|
528
645
|
RUBY_METHOD_FUNC(m_read_nonblocking), -1);
|
529
646
|
rb_define_method(rb_cLibSSHChannel, "poll", RUBY_METHOD_FUNC(m_poll), -1);
|
530
647
|
rb_define_method(rb_cLibSSHChannel, "eof?", RUBY_METHOD_FUNC(m_eof_p), 0);
|
648
|
+
rb_define_method(rb_cLibSSHChannel, "closed?", RUBY_METHOD_FUNC(m_closed_p), 0);
|
649
|
+
rb_define_method(rb_cLibSSHChannel, "open?", RUBY_METHOD_FUNC(m_open_p), 0);
|
531
650
|
rb_define_method(rb_cLibSSHChannel, "get_exit_status",
|
532
651
|
RUBY_METHOD_FUNC(m_get_exit_status), 0);
|
533
652
|
rb_define_method(rb_cLibSSHChannel, "write", RUBY_METHOD_FUNC(m_write), 1);
|
534
653
|
rb_define_method(rb_cLibSSHChannel, "send_eof", RUBY_METHOD_FUNC(m_send_eof),
|
535
654
|
0);
|
536
655
|
|
656
|
+
rb_define_singleton_method(rb_cLibSSHChannel, "select",
|
657
|
+
RUBY_METHOD_FUNC(s_select), 4);
|
658
|
+
|
537
659
|
id_stderr = rb_intern("stderr");
|
538
660
|
id_timeout = rb_intern("timeout");
|
539
661
|
}
|
data/ext/libssh_ruby/extconf.rb
CHANGED
@@ -1,9 +1,21 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
|
3
|
-
|
3
|
+
if ENV['LIBSSH_CFLAGS']
|
4
|
+
$CFLAGS = ENV['LIBSSH_CFLAGS']
|
5
|
+
else
|
6
|
+
$CFLAGS << ' -Wall -W'
|
7
|
+
end
|
8
|
+
|
9
|
+
unless have_header('libssh/libssh.h')
|
10
|
+
abort 'Cannot find libssh/libssh.h'
|
11
|
+
end
|
12
|
+
unless have_library('ssh')
|
13
|
+
abort 'Cannot find libssh'
|
14
|
+
end
|
15
|
+
unless have_library('ssh_threads')
|
16
|
+
abort 'Cannot find libssh_threads'
|
17
|
+
end
|
4
18
|
|
5
|
-
have_header('libssh/libssh.h')
|
6
|
-
have_library('ssh')
|
7
19
|
have_const('SSH_KEYTYPE_ED25519', 'libssh/libssh.h')
|
8
20
|
|
9
21
|
create_makefile('libssh/libssh_ruby')
|
@@ -1,4 +1,5 @@
|
|
1
1
|
#include "libssh_ruby.h"
|
2
|
+
#include <libssh/callbacks.h>
|
2
3
|
|
3
4
|
VALUE rb_mLibSSH;
|
4
5
|
|
@@ -26,6 +27,9 @@ static VALUE m_version(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self)) {
|
|
26
27
|
}
|
27
28
|
|
28
29
|
void Init_libssh_ruby(void) {
|
30
|
+
ssh_threads_set_callbacks(ssh_threads_get_pthread());
|
31
|
+
ssh_init();
|
32
|
+
|
29
33
|
rb_mLibSSH = rb_define_module("LibSSH");
|
30
34
|
|
31
35
|
/* @see Session#server_known */
|
data/lib/libssh/version.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'libssh'
|
2
|
-
require 'io/wait'
|
3
2
|
require 'sshkit/backends/abstract'
|
4
3
|
require 'sshkit/backends/connection_pool'
|
5
4
|
|
@@ -53,8 +52,12 @@ module SSHKit
|
|
53
52
|
scp.init do
|
54
53
|
scp.push_file(File.basename(remote), io.size, mode)
|
55
54
|
info "Uploading #{remote}"
|
56
|
-
|
57
|
-
|
55
|
+
begin
|
56
|
+
loop do
|
57
|
+
scp.write(io.readpartial(BUFSIZ))
|
58
|
+
end
|
59
|
+
# rubocop:disable Lint/HandleExceptions
|
60
|
+
rescue EOFError
|
58
61
|
end
|
59
62
|
end
|
60
63
|
end
|
@@ -110,33 +113,24 @@ module SSHKit
|
|
110
113
|
|
111
114
|
with_session do |session|
|
112
115
|
channel = LibSSH::Channel.new(session)
|
113
|
-
io = IO.for_fd(session.fd, autoclose: false)
|
114
116
|
channel.open_session do
|
115
117
|
if Libssh.config.pty
|
116
118
|
channel.request_pty
|
117
119
|
end
|
118
120
|
channel.request_exec(cmd.to_command)
|
119
121
|
until channel.eof?
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
output.log_command_data(cmd, :stdout, buf)
|
127
|
-
else
|
128
|
-
break
|
129
|
-
end
|
122
|
+
LibSSH::Channel.select([channel], [], [], nil)
|
123
|
+
|
124
|
+
buf = channel.read_nonblocking(BUFSIZ)
|
125
|
+
if buf && !buf.empty?
|
126
|
+
cmd.on_stdout(channel, buf)
|
127
|
+
output.log_command_data(cmd, :stdout, buf)
|
130
128
|
end
|
131
129
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
output.log_command_data(cmd, :stderr, buf)
|
137
|
-
else
|
138
|
-
break
|
139
|
-
end
|
130
|
+
buf = channel.read_nonblocking(BUFSIZ, stderr: true)
|
131
|
+
if buf && !buf.empty?
|
132
|
+
cmd.on_stderr(channel, buf)
|
133
|
+
output.log_command_data(cmd, :stderr, buf)
|
140
134
|
end
|
141
135
|
end
|
142
136
|
|
@@ -182,30 +176,26 @@ module SSHKit
|
|
182
176
|
end
|
183
177
|
end
|
184
178
|
|
185
|
-
def with_session
|
179
|
+
def with_session(&block)
|
186
180
|
host.ssh_options = Libssh.config.ssh_options.merge(host.ssh_options || {})
|
187
|
-
|
188
|
-
|
189
|
-
session.host = hostname
|
190
|
-
username = ssh_options.fetch(:user, username)
|
191
|
-
if username
|
192
|
-
session.user = username
|
193
|
-
end
|
194
|
-
configure_session(session, ssh_options)
|
195
|
-
session.connect
|
196
|
-
if session.server_known != LibSSH::SERVER_KNOWN_OK
|
197
|
-
raise 'unknown host'
|
198
|
-
end
|
199
|
-
if session.userauth_publickey_auto != LibSSH::AUTH_SUCCESS
|
200
|
-
raise 'authorization failed'
|
201
|
-
end
|
202
|
-
end
|
203
|
-
end
|
181
|
+
self.class.pool.with(method(:create_session), String(host.hostname), host.username, host.netssh_options, &block)
|
182
|
+
end
|
204
183
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
184
|
+
def create_session(hostname, username, ssh_options)
|
185
|
+
LibSSH::Session.new.tap do |session|
|
186
|
+
session.host = hostname
|
187
|
+
username = ssh_options.fetch(:user, username)
|
188
|
+
if username
|
189
|
+
session.user = username
|
190
|
+
end
|
191
|
+
configure_session(session, ssh_options)
|
192
|
+
session.connect
|
193
|
+
if session.server_known != LibSSH::SERVER_KNOWN_OK
|
194
|
+
raise 'unknown host'
|
195
|
+
end
|
196
|
+
if session.userauth_publickey_auto != LibSSH::AUTH_SUCCESS
|
197
|
+
raise 'authorization failed'
|
198
|
+
end
|
209
199
|
end
|
210
200
|
end
|
211
201
|
|
data/libssh.gemspec
CHANGED
@@ -26,6 +26,6 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_development_dependency 'rake-compiler'
|
27
27
|
spec.add_development_dependency 'rspec', '>= 3.0.0'
|
28
28
|
spec.add_development_dependency 'rubocop', '>= 0.36.0'
|
29
|
-
spec.add_development_dependency 'sshkit'
|
29
|
+
spec.add_development_dependency 'sshkit', '>= 1.9.0'
|
30
30
|
spec.add_development_dependency 'yard'
|
31
31
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: libssh
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kohei Suzuki
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -86,14 +86,14 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
89
|
+
version: 1.9.0
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
96
|
+
version: 1.9.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: yard
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -130,6 +130,7 @@ files:
|
|
130
130
|
- bin/console
|
131
131
|
- bin/setup
|
132
132
|
- example/exec.rb
|
133
|
+
- example/local_forward.rb
|
133
134
|
- example/scp_download.rb
|
134
135
|
- example/scp_upload.rb
|
135
136
|
- example/sshkit.rb
|
@@ -167,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
167
168
|
version: '0'
|
168
169
|
requirements: []
|
169
170
|
rubyforge_project:
|
170
|
-
rubygems_version: 2.
|
171
|
+
rubygems_version: 2.6.1
|
171
172
|
signing_key:
|
172
173
|
specification_version: 4
|
173
174
|
summary: Ruby binding for libssh.
|