string to array conversion is empty when in WSL but works fine in linux - linux

I am trying out this simple commands in WSL (Ubuntu):
$ OS="windows redhat centos ubuntu"
$ ARR_OS=($OS)
$ echo ${ARR_OS[0]}
<BLANK OUTPUT>
$ echo ${ARR_OS[1]}
windows redhat centos ubuntu
And it has a different output if the same commands executed in Linux:
$ OS="windows redhat centos ubuntu"
$ ARR_OS=($OS)
$ echo ${ARR_OS[0]}
windows
$ echo ${ARR_OS[1]}
redhat
I was expecting that WSL works very similar with Ubuntu Linux but I'm having some difficulty trying to get this to work.
Any idea why WSL output is not the same?
EDIT:
I have attached a sample run in my WSL terminal and incorporate suggestions in the comments as well
SEE:
Screenshot of WSL Terminal Output in Windows 10
Strange, I have tried the exact commands in OSX and produces the same result:
→ echo $SHELL
/bin/zsh
→ bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)
Copyright (C) 2007 Free Software Foundation, Inc.
→ OS="windows redhat centos ubuntu"
→ ARR_OS=($OS)
→ declare -p ARR_OS
typeset -a ARR_OS=( 'windows redhat centos ubuntu' )
→ echo ${ARR_OS[0]}
<BLANK>
→ echo ${ARR_OS[1]}
windows redhat centos ubuntu
UPDATE:
I have found this excellent post that explains the array differences when in zsh and bash:
https://blog.mimacom.com/arrays-on-linux-shell/

Related

How to get some information from remote machine by using shell script?

First of all, sorry for dummy question.
I would like to get distribution information from remote target by using following sample code under shell script. My local machine is Ubuntu16.04 and remote target is Ubuntu20.04(192.168.100.15). However, when I run shell script, the $distribution value is ubuntu16.04.
Why the value is not Ubuntu20.04? and How should I modify my code correctly?
ssh root#192.168.100.15 "distribution=$(. /etc/os-release;echo ) && echo $distribution"
Check the contents of /etc/os-release to find out which variables are available, then echo one of those. For example:
$ ssh root#192.168.100.15 '. /etc/os-release; echo $PRETTY_NAME'
Ubuntu 20.04.3 LTS
If you want to populate the distribution variable on your local machine, you need to use the $(...) construct locally:
$ distribution=$(ssh root#192.168.100.15 '. /etc/os-release; echo $PRETTY_NAME')
$ echo $distribution
Ubuntu 20.04.3 LTS
By the way, giving ssh access to the root user is frowned upon nowadays. And using root in this case is entirely unneccesary anyway, because /etc/os-release is world-readable to any user.
Use lsb_release:
ssh root#192.168.100.15 'lsb_release -ds'
LSB means Linux Standard Base. The command should be available on every Linux system.

strange adb behaviour if script is piped into bash

I stumpled upon a strange behaviour that I can not explain. I tried to narrow down the problem. I have the following test testscript.sh script:
echo before
adb shell ls
echo after
If I run the script with bash -x testscript.sh, everything works as expected and I get the following output:
+ echo before
before
+ adb shell ls
acct
bin
bugreports
...
sdcard
storage
sys
system
ueventd.rc
vendor
+ echo before
before
But if I run the script as piped script with cat testscript.sh | bash -sx, I get the following output:
+ echo before
before
+ adb shell ls
acct
bin
bugreports
...
sdcard
storage
sys
system
ueventd.rc
vendor
The last echo after is not executed, and I can not figure out why. The script is running on an Ubuntu server 18.04. The adb is the one from the official Ubuntu package.
$ adb --version
Android Debug Bridge version 1.0.39
Version 1:8.1.0+r23-5~18.04
Installed as /usr/lib/android-sdk/platform-tools/adb
$ bash --version
GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
Please could someone enlight me, what is happening here.
When you run a script with bash scriptname, standard input of all the commands it runs is still connected to the terminal. So adb will read its standard input from the terminal.
When you redirect the input of bash, this redirection is inherited by adb. Unless you use the -n option to adb shell, it will read additional input from standard input and send it to the remote system as possible input for the command you run (it doesn't know that ls doesn't read standard input).
Change it to
adb shell -n ls

Linux doesn't seems to capture some characters

Last night I was making some bash script, just using proc and cat.
But suddenly, I think it broke or something like that my on Linux Installation.
What I can't do at the moment of posting is:
PuTTY doesn't seems to "accept"/register/capture the following keys. (Tried on 2 computers)
a
i
p
s
f
m
w
c
v
b
I've tried on 3 servers.
Debian 7 32Bit - nothing wrong
CentOS 6 32Bit - doesn't work
Ubuntu 12.04 32Bit -doesn't work
I haven't tried to reinstall them because my CentOS server runs cPanel and I don't want to start over again and my Ubuntu server runs like 8 TeamSpeak3 server (not a big job but people will complain).
Screenshot:
#!/bin/bash
echo "Hang on, saving CPU Info" &&
CPU=$(sudo cat /proc/cpuinfo) &&
cat >test.txt <<EOF
$CPU
EOF
I'm new to bash scripting :s

Better way to check linux version?

What I currently have. Is this the best way? Have a script with lots of functions and need a way to know what OS is running before running each function.
CHECK_architecture()
{
architecture=`uname -m`
if [ "$architecture" != "x86_64" ] && [ "$architecture" != "ia64" ]; then
architecture="x86"
else
architecture="x86_64"
fi
}
CHECK_distro()
{
DISTRO="";
if [ `uname -r | egrep '(6.2-RELEASE|6.1-RELEASE|5.5-RELEASE|6.1-STABLE|5.4-RELEASE|6.0-RELEASE|5.3-RELEASE|4.10-RELEASE|4.11-RELEASE)'` ]; then
DISTRO="FreeBSD";
$BIN_ECHO " System is running FreeBSD"
elif [ -f /etc/debian_version ]; then
$BIN_ECHO " System is running Debian Linux"
DISTRO=DEBIAN;
elif [ -f /etc/SuSE-release ]; then
$BIN_ECHO " System is running SuSE Linux"
DISTRO=SUSE;
elif [ -f /etc/fedora-release ]; then
$BIN_ECHO " System is running Fedora Linux"
DISTRO=FEDORA;
elif [ -f /etc/redhat-release ]; then
$BIN_ECHO " System is running Red Hat Linux"
DISTRO=REDHAT;
else
$BIN_ECHO -e " no supported distribution found running "
exit 1
fi
}
From the Linux Standard Base article at wikipedia:
The Linux Standard Base (LSB) is a joint project by several Linux distributions under the organizational structure of the Linux Foundation to standardize the software system structure, including the filesystem hierarchy, used with Linux operating system. The LSB is based on the POSIX specification, the Single UNIX Specification, and several other open standards, but extends them in certain areas.
According to the LSB:
The goal of the LSB is to develop and promote a set of open standards that will increase compatibility among Linux distributions and enable software applications to run on any compliant system even in binary form. In addition, the LSB will help coordinate efforts to recruit software vendors to port and write products for Linux Operating System.
If you are using some LSB compliant distribution (and you should), just man lsb_release:
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 8.04.4 LTS
Release: 8.04
Codename: hardy
$ lsb_release -a
LSB Version: :core-3.1-amd64:core-3.1-ia32:core-3.1-noarch:graphics-3.1-amd64:graphics-3.1-ia32:graphics-3.1-noarch
Distributor ID: CentOS
Description: CentOS release 5.5 (Final)
Release: 5.5
Codename: Final
You are looking for the config.guess utility. It will reliably determine the architecture and OS, and give you a standardized moniker which many other tools use. It will not tell you precisely which Linux distribution you have, but you should not need that information -- please explain what you are using it for, and I can give further advice.
There isn't an absolutely reliable way to check the Linux distribution and its version.
$ head -n1 /etc/issue
Actually, it depends on the type of linux OS you are running. To me, best way to get the version of linux you are on is from /etc/redhat-release if you are on Redhat. For other,
Redhat: Test for /etc/redhat-release, check contents
Debian: Test for /etc/debian_version, check contents
Mandriva: Test for /etc/version, check contents
Slackware: Test for /etc/slackware-version, check contents
Generally speaking, check for /etc/*-release and /etc/*-version
Probably most correct and easiest way is to follow Free Standards Group, and use lsb-release: http://linux.die.net/man/1/lsb_release

How to get Linux distribution name and version?

In Windows I read the registry key SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName to get the full name and version of the OS.
But in Linux, the code
struct utsname ver;
uname(&ver);
retVal = ver.sysname;
returns the string linux, not Ubuntu 9.04.
How can I get the Linux distribution name and version?
Try:
cat /etc/lsb-release
You can also try
lsb_release -a
Or:
cat /proc/version
lsb_release -ds ; uname -mr
on my system yields the following from the bash (terminal) prompt:
Ubuntu 10.04.4 LTS
2.6.32-41-generic x86_64
trying this way is an interesting one and less restrictive than lsb-release.
$ cat /etc/*-release
What's the purpose of getting that information?
If you're trying to detect some features or properties of the system (e.g. does it support some syscall or does it have some library), instead of relying on output of lsb_release you should either:
try to use given features and fail gracefully (e.g. dlopen for libraries, syscall(2) for syscalls and so on)
make it a part of your ./configure check if applicable (standard FOSS way of automatically recognizing system features/properties)
Note that the first way above applies even if your software is binary-only.
Some code examples:
dl = dlopen(module_path, RTLD_LAZY);
if (!dl) {
fprintf(stderr, "Failed to open module: %s\n", module_path);
return;
}
funcptr = dlsym(dl, module_function);
if (!funcptr) {
fprintf(stderr, "Failed to find symbol: %s\n", module_function);
return;
}
funcptr();
dlclose(dl);
You can even gracefully test for CPU opcodes support, read e.g. http://neugierig.org/software/chromium/notes/2009/12/flash-lahf.html , http://code.google.com/p/chromium/issues/detail?id=29789
Not sure I followed exactly what you're after but I think you just want the "all" flag on uname:
uname -a
/etc/os-release is available on at least both CentOS 7 and Ubuntu 16.04, which makes it more cross-platform than lsb_release (not on CentOS) or /etc/system-release (not on Ubuntu).
$ cat /etc/os-release
Example:
NAME=Fedora
VERSION="17 (Beefy Miracle)"
ID=fedora
VERSION_ID=17
PRETTY_NAME="Fedora 17 (Beefy Miracle)"
ANSI_COLOR="0;34"
CPE_NAME="cpe:/o:fedoraproject:fedora:17"
HOME_URL="https://fedoraproject.org/"
BUG_REPORT_URL="https://bugzilla.redhat.com/"
Usually:
cat /etc/issue
cat release file to display Linux distro version
$ cat /etc/*-release
lsb_release will return Linux distribution name and version
$ lsb_release -a
hostnamectl will return Linux distribution name and version
$ hostnamectl
To print certain system information
$ uname -a
or
-s, --kernel-name print the kernel name
-n, --nodename print the network node hostname
-r, --kernel-release print the kernel release
-v, --kernel-version print the kernel version
-m, --machine print the machine hardware name
-p, --processor print the processor type (non-portable)
-i, --hardware-platform print the hardware platform (non-portable)
-o, --operating-system print the operating system
To find out Static hostname, Chassis, Mchine ID, Virtualization, OS, Kernel, Architecture
$ cat /proc/version

Resources