Query a remote server’s operating system

Query a remote server’s operating system

I’m writing a microservice in Node.js, that runs a particular command line operation to get a specific piece of information. The service runs on multiple server, some of them on Linux, some on Windows. I’m using ssh2-exec to connect to the servers and execute a command, however, I need a way of determining the server’s OS to run the correct command.
let ssh2Connect = require(‘ssh2-connect’);
let ssh2Exec = require(‘ssh2-exec’);

ssh2Connect(config, function(error, connection) {
let process = ssh2Exec({
cmd: ‘‘,
ssh: connection
});
//using the results of process…
});

I have an idea for the solution: following this question, run some other command beforehand, and determine the OS from the output of said command; however, I want to learn if there’s a more “formal” way of achieving this, specifically using SSH2 library.

Solutions/Answers:

References

How to protect yourself against shell DLLs loaded into your process?

How to protect yourself against shell DLLs loaded into your process?

When you use a standard Windows “file open” dialog using GetOpenFileName(), the shell will load various DLLs that it requires to display the file list, including custom ones.
In my application, I found that the DLL that TortoiseCVS uses to draw overlays on the icons was calling GdiPlusShutdown(), and so some time after displaying a “file open” dialog, the TortoiseCVS DLL would be unloaded, it would shut down GDI+ and my graphics functions would all fail!
It seems quite bad that basically any old DLL could be loaded by my application at any time and start doing random things to its state. The workaround in my case was quite simple – just restart GDI+ if I detect that it’s been shut down. However had this happened on a client’s machine where I couldn’t debug it, it would have been a lot more challenging to figure out what was going on.
Can anybody offer any insight? What could I do to stop this from happening?

Solutions/Answers:

Solution 1:

I’ve had to deal with the crap that Dell puts on its machines, in particular wxVault. My solution was to “simply” patch the code. Slightly tricky with DEP, but still doable. You could have a peek at Microsoft Detours, which is a slightly more structured way to do the same. You’d still have the DLL load, but at least you can stop it calling functions that it should not be calling.

At to why Windows has such a crappy mechanism, read Raymond Chen’s “Old New Thing” blog or book.

References

How do a run a bash script on save in NetBeans?

How do a run a bash script on save in NetBeans?

I am using NetBeans 6.5 and whenever I save a LessCSS file I would like to run less compiler to compile it to native css. How do I go about achieving this?
Many Thanks.
Ravi
EDIT: I can do a build file as Kim recommended below. I am searching for a solution where I can run an external command. So the question now is How Do I Run an External Command using Ant?

Solutions/Answers:

Solution 1:

Does it have to be on save? Instead, you could create a custom project (with a custom build file) and just put it into that build file.

References

Can you write a simple weekly reminder using a bash/sh script quine?

Can you write a simple weekly reminder using a bash/sh script quine?

I need to set myself a reminder to attend a weekly meeting. The trouble with my company’s standard reminder tool is that when it runs under wine, it pops up on an off-screen virtual desktop.
I thought it would be interesting to see if I could come up with an “at” command that pops up a reminder window and then resubmits itself for the following week.
I know I could use cron or some alarm-clock app but this piqued my curiosity.
The single-shot version would be:
echo “DISPLAY=$DISPLAY zenity –title=’Weekly Meeting’ –text=’Time for the weekly meeting’ –info” | at 0955 NEXT Monday

Can someone come up with a suitable quine-like command that, each time it is run, it will additionally resubmit the same command the following week in a repeating cycle?

Solutions/Answers:

Solution 1:

Give this a try:

export reminder='"DISPLAY=$DISPLAY zenity --title='\''Weekly Meeting'\'' --text='\''Time for the weekly meeting'\'' --info" | at 0955 NEXT Monday'; echo $reminder | at 0955 NEXT Monday

Change both at commands to say at now + 1 minute for testing. $DISPLAY will be set when the command is entered and may not be correct at the time the job executes, but this is the same behavior as the command in your question.

Solution 2:

Try with a file:

$ cat /tmp/quine_file
DISPLAY=:0.0 zenity --title='Weekly Meeting' --text='Time for the weekly meeting' --info;
at '0955 NEXT monday' </tmp/quine_file;

$ at '0955 NEXT monday' </tmp/quine_file

This way, every time the job is run, another one is scheduled for next monday.

Solution 3:

I’m probably cheating, but you can take advantage of the fact that
at conserves the value of most environment variables
(not $DISPLAY though, neither $DISP it seems):

export FOO=$DISPLAY CMD='DISPLAY=$FOO xmessage "hi there";
echo "$CMD" | at now + 1 minutes'
eval "$CMD"

I used xmessage and one minute because I had them,
but of course you can tailor it to your needs.

Solution 4:

Sorry to spoil the fun, but… wouldn’t some sort of cron job make more sense?

References

What is common between environments within a shell terminal session?

What is common between environments within a shell terminal session?

I have a custom shell script that runs each time a user logs in or identity is assumed, its been placed in /etc/profile.d and performs some basic env variable operations. Recently I added some code so that if screen is running it will reattach it without needing me to type anything. There are some problems however. If I log-in as root, and su – to another user, the code runs a second time. Is there a variable I can set when the code runs the first time that will prevent a second run of the code?
I thought to write something to the disk but then I dont want to prevent the code from running if I begin a new terminal session. Here is the code in question. It first attempts to reattach – if unsuccessful because its already attached (as it might be on an interruped session) it will ‘take’ the session back.
screen -r

if [ -z “$STY” ]; then
exec screen -dR
fi

Ultimately this bug prevents me from substituting user to another user because as soon as I do so, it grabs the screen session and puts me right back where I started. Pretty frustrating

Solutions/Answers:

Solution 1:

The ${PPID} of the shell you get when you su will be the su command. So the output of

ps -o command= $PPID

will begin with the letters su, so test for this.

Solution 2:

I think you can get this right if you read the following post (and the man for your favorite shell)
Question about login vs profile

References

How can I find out the original username a process was started with?

How can I find out the original username a process was started with?

There is a perl script that needs to run as root but we must make sure the user who runs the script did not log-in originally as user ‘foo’ as it will be removed during the script.
So how can I find out if the user, who might have su-ed several times since she logged in has not impersonated ‘foo’ at any time in that chain?
I found an interesting perl script that was calling the following two shell scripts, but I think that would only work on Solaris.
my $shell_parent =
`ps -ef | grep -v grep | awk \'{print \$2\” \”\$3}\’ | egrep \”^@_\” | awk \'{print \$2}’`;

my $parent_owner =
`ps -ef | grep -v grep | awk \'{print \$1\” \”\$2}\’ | grep @_ | awk \'{print \$1}\’`;

This needs to work on both Linux and Solaris and I’d rather eliminate the repeated calls to he the shell and keep the whole thing in Perl.

Solutions/Answers:

Solution 1:

Quick and dirty and (UNIX only):

my $user = (split /\s/,`who am i`)[0];

The who am i command returns the owner of the TTY – i.e. who you were when you logged in.

If you want to do this in pure perl:

use POSIX;
my $tty = POSIX::ttyname(1); # The tty we are running in
my $uid = (stat $tty)[4];    # The owner uid of that tty
my $user = getpwuid($uid);   # The user with that uid

This will return the correct user, even after multiple su’s. This usually freaks out your (less experienced) sysadmins.

Solution 2:

Here’s a Perl program that checks for direct setuid change:

#! /usr/bin/perl

sub callingUser() {
    my ($login, $pass, $uid, $gid) = getpwuid($<);
    return $login;
}

sub effectiveUser() {
    my ($login, $pass, $uid, $gid) = getpwuid($>);
    return $login;
}

printf("Real user name: %s\n", effectiveUser());
printf("Calling user name: %s\n", callingUser());

But since you mentioned that the setuid change may have occured anytime before, you probably have to parse the output of ps: I would do it using the following command. This command only uses features defined in POSIX, so I hope it is portable to all kinds of systems:

ps -e -o pid,ppid,user,ruser

Solution 3:

Maybe the following is what you want. The function hasBeenUser reads the process table and then follows the process chain from the current process down the parent process. If any of the processes on the way has a user or real user field equal to the username in question, the function returns a nonzero value.

#! /usr/bin/perl

sub hasBeenUser($) {
        my ($username) = @_;

        my $procs = {};
        open(PS, "ps -e -o pid,ppid,user,ruser |") or die;
        while (defined(my $line = <PS>)) {
                next unless $line =~ m"^(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+$";
                my ($pid, $ppid, $user, $ruser) = (int($1), int($2), $3, $4);
                $procs->{$pid} = [$pid, $ppid, $user, $ruser];
        }
        close(PS) or die;

        my $pid = $$;
        while (exists($procs->{$pid})) {
                my $proc = $procs->{$pid};
                delete $procs->{$pid}; # don't risk ending in an endless loop.
                warn "D: checking process $pid\n";
                if ($proc->[2] eq $username || $proc[3] eq $username) {
                        warn "E: process $pid was called by $username.\n";
                        return 1;
                }
                last if $pid < 2;
                $pid = $proc->[1];
        }
        return 0;
}

hasBeenUser("del"); # should return 0
hasBeenUser("root"); # should return nonzero

Solution 4:

I recognized a corner case when calling scripts from mc (at least in our RHEL’s), which results that the who am i does not output anything. To circumvent that, I produced the following one-liner in bash:

REALUSERNAME=$(ps uhp `ps -AjH | grep \`ps -u $USER fh | awk '{ print $0; if(index($0, "ps -u $USER fh")) exit 0;}' | tac | awk '{if(!index($0, "\\\\\_")){print $1; exit 0;}}'\` | awk '{print $3}'` | awk '{print $1}')

Essentially, this walks backwards on the tree output of ps -u $USER fh and then crops on the topmost username column.

Thoughts, better solutions are welcome 🙂

References

Add a function to a program, and call that function from the command line in the function

Add a function to a program, and call that function from the command line in the function

I have to add a custom function which shows currently running foreground and background processes launched by this shell. How do I define and call that function from the shell’s command line?
#include “smallsh.h” /*include file for example*/

/*program buffers and work pointers*/
static char inpbuf[MAXBUF], tokbuf[2*MAXBUF],
*ptr = inpbuf, *tok = tokbuf;

userin(p) /*print prompt and read a line*/
char *p;
{

int c, count;

/*initialization for later routines*/
ptr = inpbuf;
tok = tokbuf;

/*display prompt*/
printf(“%s “,p);

for(count = 0;;)
{
if((c = getchar()) == EOF)
return(EOF);

if(count

main()
{
while(userin(prompt) != EOF)
procline();
}

To try to call a function, Inside of runcommand, before the code for the child process, I tried to add another if statement saying if(cline == “dowork”){dowork();}, and tried putting in similar lines elsewhere, but nothing like that works.

Solutions/Answers:

Solution 1:

Since this is C, cline == "dowork" will not do what you want. You need to change that to:

if (strcmp(cline, "dowork") == 0)
{
    ...
}

If you wanted your shell to also handle “DOWORK”, “DoWork”, etc. you can replace strcmp with strcasecmp.

Update: since you have char **cline, you need to change that to:

if (strcmp(*cline, "dowork") == 0)

Also, you should be compiling with warnings – if you do that the compile will have told you you had a type mismatch here.

Solution 2:

You could maintain a list of internal commands like:

cd” “ls” and check the user input against this list, if an internal command is regonized simply call the function that implements the internal command.

EDIT: I was assuming you’re implementing a small shell like application.

References