No Gui Option? - shoes

Ok, well I'm really pushing the bounds as to what shoes is for here, so I don't expect any miracles: is there a way to optionally run a shoes app without a gui?
The reason I'd like to do this is I'm creating a tool for use by "non computer people", as well as "computer people", who would rather just run the program as a command line tool, maybe even on systems without X/gtk installed. (I work as a multidisciplinary researcher, and shoes is great for focusing on tools and not fiddling with gui design all day.)
Here's some example code:
if(ARGV[1] == "nogui")
puts "running computation on #{ARGV[2]}";
exit();
end
Shoes.app(:width => 200, :height => 100) do
#button = button("Quit").click() {
exit();
}
end
which works except I get a
Gtk-CRITICAL **: gtk_main_quit: assertion `main_loops != NULL' failed
error.

I haven't tried it, but I don't know that Shoes will even happily start on a system without X. You're probably better off creating a shell script that chooses which version to start. Something like this:
#!/usr/bin/sh
NOGUI=0
if [ $# -gt 0 ]; then
NOGUI=$1
fi
if [ $NOGUI = nogui ]; then
shift
echo "Running in command-line mode..."
ruby command-line.rb "$#"
else
echo "Starting Shoes..."
shoes shoes.rb "$#"
fi
If the first argument is nogui, the remaining arguments are sent to the Ruby version, otherwise all arguments (including the first) are sent to Shoes.
Now you just need to separate the actual performance logic out so that it can be imported into both versions.

Related

Terraform GCP Instance Metadata Startup Script Issue

I've been working with Terraform, v0.15.4, for a few weeks now, and have gotten to grips with most of the lingo. I'm currently trying to create a cluster of RHEL 7 instances dynamically on GCP, and have, for the most part, got it to run okay.
I'm at the point of deploying an instance with certain metadata passed along to it for use in scripts built into the machine image for configuration thereafter. This metadata is typically just passed via an echo into a text file, which the scripts then pickup as required.
It's... very simple. Echo "STUFF" > file... Alas, I am hitting the same issue OVER AND OVER and it's driving me INSANE. I've Google'd around for ages, but all I can find is examples of the exact thing that I'm doing, the only difference is that theirs works, mine doesn't... So hopefully I can get some help here.
My 'makes it half-way' code is as follows:
resource "google_compute_instance" "GP_Master_Node" {
...
metadata_startup_script = <<-EOF
echo "hello
you" > /test.txt
echo "help
me" > /test2.txt
EOF
Now the instance with this does create successfully, although when I look onto the instance, I get one file called ' /test.txt? ' (or if I 'ls' the file, it shows as ' /test.txt^M ') and no second file.. I can run any command instead of echo, and whilst the first finishes, the second+ does not. Why?? What on earth is causing that??
The following code I found also, but it doesn't work for me at all, with the error, 'Blocks of type "metadata" are not expected here.'
resource "google_compute_instance" "GP_Master_Node" {
...
metadata {
startup-script = "echo test > /test.txt"
}
Okaaaaay! Simple answer for a, in hindsight, silly question (sort of). The file was somehow formmated in DOS, meaning the script required a line continuation character to run correctly (specifically \ at the end of each individual command). Code as follows:
resource "google_compute_instance" "GP_Master_Node" {
...
metadata_startup_script = <<-EOF
echo "hello
you" > /test.txt \
echo "help
me" > /test2.txt \
echo "example1" > /test3.txt \
echo "and so on..." > /final.txt
EOF
However, what also fixed my issue was just 'refreshing' the file (probably a word for this, I don't know). I created a brand new file using touch, 'more'd the original file contents to screen, and then copy pasted them into the new one. On save, it is no longer DOS, as expected, and then when I run terraform the code runs as expected without requiring the line continuation characters at the end of commands.
Thank you to commentors for the help :)

Piping in Windows

i am have a console to controll a device driver. This tool allows me to enter numbers an change parameters of the device. Which is executed on a windows system. In order to not enter numbers manually, I am piping those numbers to the executable, like so..
cd %tool_path%
(
echo 1
echo 2
echo 3
)myconsole.exe
And here is my question, is there a way to put a delay between those echos? And it would be even better if I could read the output, so I can send different numbers depandend on the output.
My idea would be writing a short programm in C or C++ doesn't matter and handle those delays in there. But I can't really find examples to this. Here is what I found.
https://msdn.microsoft.com/de-de/library/windows/desktop/ms682499(v=vs.85).aspx
But in this examples I don't know where I can input myconsole.exe.
I also looked at named pipes, but they don't seem to be the right thing for this task.
You should have a look at the Unix tool called expect - there is a Windows version from ActiveState.
Basically, you can do things like:
send "Hello\r\n"
sleep 1
send "Something\r\n"
expect {
"> " { }
"$ " { }
}
if { $a == "soup" } {
puts "You have soup!"
else {
puts "No soup for you!"
}
There are examples here and all over the Web - look for Tcl/expect tutorials.

How to make a ruby command line application with pager?

I'm making a command line tool using Ruby. It will print a lot of text on screen. Currently, I'm using shell pipeline (may_app | more) to do so. But I think it's better to has a default pager.
It's just like what you see when execute git log . One can disable pager by using git --nopager log.
I've done quite much google work and find one gem: hirb , but it seems a little overkill.
After many tries, I'm current using shell wrapper to do so:
#!/bin/bash
# xray.rb is the core script
# doing the main logic and will
# output many rows of text on
# screen
XRAY=$HOME/fdev-xray/xray.rb
if [ "--nopager" == "$1" ]; then
shift
$XRAY $*
else
$XRAY $* | more
fi
It works. But is there a better way?
You are doing it right. But instead using more you'd better get a pager from $PAGER environment variable, if any.
Some people prefer less to more for example, and others have their favorite parser options set in this var.
You can use the pipe in Ruby via a call to system and provide the options (along with a nice help interface) like so:
require 'optparse'
pager = ENV['PAGER'] || 'more'
option_parser = OptionParser.new do |opts|
opts.on("--[no-]pager",
"[don't] page output using #{pager} (default on)") do |use_pager|
pager = nil unless use_pager
end
end
option_parser.parse!
command = "cat #{ARGV[0]}"
command += " | #{pager}" unless pager.nil?
unless system(command)
STDERR.puts "Problem running #{command}"
exit 1
end
Now, you support --pager and --no-pager on the command line, which is nice to do.

Perl Net::SSH2 scp_put puts file and then hangs

I'm using Net::SSH2's scp_put method to place one file in my home directory on a Unix server from a Windows box. I am using Strawberry Perl 5.12 (portable version). I installed the libssh2 1.2.5 binaries and then Net::SSH2 from cpan.
Here's my code snippet:
sub uploadToHost{
my $file=#_[0];
my $host=#_[1];
my $user=#_[2];
my $pass=#_[3];
my $remotelocation=#_[4];
#makes a new SSH2 object
my $ssh=Net::SSH2->new() or die "couldn't make SSH object\n";
#prints proper error messages
$ssh->debug(1);
#nothing works unless I explicitly set blocking on
$ssh->blocking(1);
print "made SSH object\n";
#connect to host; this always works
$ssh->connect($host) or die "couldn't connect to host\n";
print "connected to host\n";
#authenticates with password
$ssh->auth_password($user, $pass) or die "couldn't authenticate $user\n";
print "authenticated $user\n";
#this is the tricky bit that hangs
$ssh->scp_put($file, $remotelocation") or die "couldn't put file in $remotelocation\n";
print "uploaded $file successfully\n";
$ssh->disconnect or die "couldn't disconnect\n";
} #ends sub
Output (edited for anonymity):
made SSH object\n
connected to host\n
authenticated \n
libssh2_scp_send_ex(ss->session, path, mode, size, mtime, atime) -> 0x377e61c\n
Net::SSH2::Channel::read(size = 1, ext = 0)\n
It then hangs forever (>40 minutes in one test) and needs to be killed.
What's strange is that it actually does scp the file to the remote server! It only hangs after it should have completed. I couldn't find references to this curious problem elsewhere on StackOverflow or elsewhere.
Can anyone point me in the right direction to either 1) stop it from hanging, or 2) implement (as a workaround) a timer that kills this one command after a few seconds, which is enough time to scp the file?
Thanks, everyone!
You can try using alarm() to prod your process into behaving, if you save this example as 'alarm.pl' you can see how it works:
use strict;
use warnings;
use 5.10.0;
# pretend to be a slow process if run as 'alarm.pl s'
if (#ARGV && $ARGV[0] eq 's') {
sleep(30);
exit();
}
# Otherwise set an alarm, then run myself with 's'
eval {
local $SIG{ALRM} = sub {die "alarmed\n"};
alarm(5);
system("perl alarm.pl s");
};
if ($#) {
die $# unless $# eq "alarmed\n";
say "Timed out slow process";
}
else {
say "Slow process finished";
}
Use Net::SFTP::Foreign with the Net::SSH2 backend, Net::SFTP::Foreign::Backend::Net_SSH2:
use Net::SFTP::Foreign;
my $sftp = Net::SFTP::Foreign->new($host, user => $user, password => $password, backend => Net_SSH2);
$sftp->die_on_error("Unable to connect to remote host");
$sftp->put($file, $remotelocation);
$sftp->die_on_error("Unable to copy file");
If that doesn't work either, you can try using plink (from the PuTTY project) instead of the Net::SSH2 backend.
I don't think it is hanging it is just REALLY SLOW. 10x slower than what it should be. The reason the file would appear to be there is that it allocates the file before it has finished transferring. This isn't really too unexpected, Perl finds new ways to disappoint and frustrate programmers on a daily basis. Sometimes I think I spend more time working around Perl's idiosyncrasies and learning 10 slightly different ways to do the same thing than doing real work.

Expect scripting, source and return

On page 35, in the book "Exploring Expect", it says "The return command can be used to make a source command return. Otherwise, source returns only after executing the last command in the file."
I don't quite understand what it's getting at. I'd like to know what this means and how this is useful.
Thank you.
an example:
main script:
puts "about to source external file"
set some_var true
source something.exp
puts "done sourcing"
something.exp
puts "in something.exp"
if {$some_var} return
puts "you won't see this if some_var is true"
Basically, when the 'return' command is encountered, 'expect' will stop processing the script further, and return to the parent script (if any) that ran it using the 'source' command. It's much like 'return' in any programming language.

Resources