execute buffer content in current shell upon exec ssh - perl

My perl code does this
#!/usr/bin/perl
sleep 2;
exec 'ssh', '-o', "ConnectTimeout=10", "newhost", "sleep 3;pwd";
the problem is when sleep is executing what ever I type on the terminal (during execution)
disappears to non interactive shell in newhost.
eg:
user#a02$perl test.pl
ls
user#a02$ #ls is not executed
command ls executes if I don't use exec or system.
Is there a way to execute the contents of the buffer?

After a bit of digging i found ssh has has an stdio redirector when used with -n option.
http://www.pixelbeat.org/programming/stdio_buffering/
To tell ssh that the remote command doesn't require any input use the -n option

Related

Using rsh in a shell script

As part of a powershell script im working on, i use rsh in order to connect to another shell however after using this all subsequent commands are ignored and the script just ends.
My workflow is:
rsh "podname"
cd "path"
exit
Everything after I use rsh is ignored. Is there a way to get the script to wait until the rsh is completed?
Using: oc rsh foo "cd /path && somecommand" resulted in an error saying that no such directory existed. Is this because it's trying to find /path on the local machine and not the remote one?
When you just run oc rsh, that is an interactive command that might interfere with your script. So when running a command inside a container, you should add the commands as an argument to the oc rsh command, here is an example:
# Run the command 'cat /etc/resolv.conf' inside pod 'foo'
oc rsh foo cat /etc/resolv.conf
So in your case something like the following could help in your case:
oc rsh foo "cd /path && somecommand"

How to log the output along with error messages to a file while running a script on psql command line on Freebsd OS?

On RHEL, the below command works:
psql -h hostname -U username -p port_no -d database -f /tmp/myfile.sql &> logfile01.txt
On FreeBSD, this throws error:
"Invalid null command"
Please suggest.
If you use this only on the command line then there is no need to change the shell.
To redirect stdout and stderr to a file in C-Shell synthax simply use ">& filename".
Different story is, if you want to write shell scripts. Bourne Shell and it's clones (like i.e. Bash) are better suited for writing script. See this Unix FAQ "Csh Programming Considered Harmful": http://www.faqs.org/faqs/unix-faq/shell/csh-whynot/
This redirection works in bash
&> logfile01.txt
, but it does not work in csh which is the default shell in FreeBSD.
# set | grep shell
shell /bin/csh
# ls -la &> logfile01.txt
Invalid null command.
Bash is not installed by default. You can install it
pkg install bash
and configure it as the default shell.

execution of system command from perl script using su

I have a perl script as below:
test.pl
#!/usr/bin/perl
system("ls -lart");
this works fine but when i run it as below it is failing:
su guest test.pl
it is failing at 2nd line as below:
0403-057 Syntax error at line 2 : `(' is not expected.
From man 1 su:
OPTIONS
The options which apply to the su command are:
-c, --command COMMAND
Specify a command that will be invoked by the shell using its -c.
The executed command will have no controlling terminal. This option cannot be used to execute interractive programs which need a controlling TTY.
So you should use
su -c "perl /path/to/test.pl --maybe some.options" guest
You have to execute it using -c option for su. The problem is that if you launch it like that, it's supposed to be a shell script. So you have to tell su to actually load the shell and then execute the command.
Most likely
su guest -c test.pl
will work (provided it's in the command path of the user, of course).

Determine if the stdout is terminal under ssh

To test whether the output is terminal we can do -t STDOUT:
if (-t STDOUT) {
# print with terminal control chars
} else {
# just plain print
}
But when the script is executed in the ssh session not run from terminal (Jenkins in my case), the -t test still returns true and my output gets polluted with control chars:
ssh user#server "/my/script.pl"
Why does the -t detects the terminal?
I don't know why ssh is allocating a terminal for you — mine defaults to not doing that even if the output of ssh goes to a terminal — but passing -T to ssh will disable pseudo-tty creation on the remote end.
$ ssh -t localhost "perl -E'say -t STDOUT ?1:0'"
1
Connection to localhost closed.
$ ssh -T localhost "perl -E'say -t STDOUT ?1:0'"
0
From ssh's man page:
-T Disable pseudo-tty allocation.
-t Force pseudo-tty allocation. This can be used to execute arbitrary
screen-based programs on a remote machine, which can be very useful,
e.g. when implementing menu services. Multiple -t options force tty
allocation, even if ssh has no local tty.
Perhaps it would be better if you instead forced ssh to allocate a pty —
From the ssh manual:
-t Force pseudo-tty allocation. This can be used to execute arbitrary screen-based programs
on a remote machine, which can be very useful, e.g. when implementing menu services.
Multiple -t options force tty allocation, even if ssh has no local tty.
The longer answer: -t (the Perl or Bourne shell function) reliably detects whether the stream is a “typewriter,” but ssh will normally only allocate a pseudo-teletype (pty) stream in interactive shells, not when other programs are being started.
See also RequestTTY as an option in .ssh/config.

perl run two system commands error

So in my script I need to make to calls to unix, and I do it via the system command like so:
system "bash -i -c 'addmothernode'";
...
perl code ...
...
system "bash -i -c 'addnode -ip=$_'";
However, whenever I run both of these commands in the same script, for some reason my process is stopped like this:
[1]+ Stopped perl boot.pl
And the script can only be finished when I run fg %1. When I only have one of these system calls in, the perl script finishes successfully. But I need both commands because they depend on each other. Anyone have any ideas about what's going on? Thanks!
UPDATE:
A lot of answers below are saying I don't need to use bash -i to run a system command, and I know typically this is true but I need to use aliases that I have created and if I do not use this the aliases won't be recognized. So I do need bash -i.
This problem is unrelated to perl. You can easily reproduce the situation if you start two bashes in the interactive mode (-i) one after another:
$ cat 1.sh
bash -i -c 'sleep 1'
bash -i -c 'sleep 1'
$ bash 1.sh
[1]+ Stopped bash 1.sh
Of course it would be better to run bash in the non-interactive mode (without -i) or run the program directly, without bash, but if you need for some reason bash -i you can protect its run with setsid:
$ cat 1.sh
setsid bash -i -c 'sleep 1'
setsid bash -i -c 'sleep 1'
echo done
$ bash 1.sh
done
The bash -i means run an interactive shell; so you have two shells both reading from the terminal.
Try removing the -i options.
system "addmothernode";
should work.
To execute a command, bash is not needed. The Perl system function is like the system C function, it calls by default sh.
man system
exec
The standard to which the caller conforms determines which shell is used. See standards(5).
Standard Shell Used
______________________________________________________________
1989 ANSI C, 1990 ISO C, 1999 ISO C, /usr/xpg4/bin/sh
POSIX.1 (1990-2001), SUS, SUSv2, SUSv3,
XPG4
POSIX.1 (1988), SVID3, XPG3, no standard /usr/bin/sh
specified