How to check if Linux user namespaces are supported by current OS kernel - linux

After doing some reading, I found that Linux user namespaces are generally supported in Linux versions >= 3.8. However, there's a possibility that user namespaces are disabled on a given OS, making the check for kernel versions unreliable. Is there a robust way to check if the current OS I'm using supports user namespaces and has it available to use?

You could check if your current process' /proc/[pid]/ns/ directory has a file called user:
ls /proc/self/ns

There are two places you can check to see if your kernel supports user namespaces:
/boot/config-*. (find out which one you are actually using with uname -a)
/proc/config.gz.
In both files look for CONFIG_USER_NS. If it reads CONFIG_USER_NS=y you're golden. If not, well, you're about to compile a new kernel.

Provided you are running bash (you can check by running echo $0, expected result is -bash). Then you can run the following one liner:
if [[ `sudo cat /boot/config-$(uname -a | awk '{print $3}') |grep '^CONFIG_USER_NS'` == "CONFIG_USER_NS=y" ]]; then echo "You have support for User Namespaces"; else echo "Sorry, you don't have support for User Namespaces"; fi

Related

Most efficient if statement in .zshrc to check whether Linux OS is running on WSL?

In my .zshrc file I conditionally set my PATH variable depending on whether I'm running on Linux or macOS - I'm now trying to figure out if there's a way I can efficiently detect from my .zshrc if I'm working on Linux running on WSL.
I'm wondering if I can somehow check for the existence of /mnt/c/Program Files or similar - but figure there must be a better way?
Example of my current .zshrc:
PATH="/usr/local/sbin:$PATH"
if ! [[ "$OSTYPE" == "darwin"* ]]; then
export PATH="$HOME/.nodenv/bin:$HOME/.rbenv/bin:$PATH"
fi
eval "$(rbenv init -)"
eval "$(nodenv init -)"
PATH="$HOME/.bin:$PATH"
if [[ "$OSTYPE" == "darwin"* ]]; then
export ANDROID_SDK_ROOT="$HOME/Library/Android/sdk"
export PATH="$PATH:$ANDROID_SDK_ROOT/tools:$ANDROID_SDK_ROOT/tools/bin:$ANDROID_SDK_ROOT/platform-tools:$ANDROID_SDK_ROOT/build-tools:$ANDROID_SDK_ROOT/tools/lib/x86_64"
export PATH="$PATH:/usr/local/share/dotnet"
fi
If anyone has any better ideas than somehow checking for the existence of /mnt/c/Program Files I'd very much appreciate it!
There are many possible way to check WSL in any shell. Most reliable ways are:
From uname -r command output.
From /proc/version file.
From /proc/sys/kernel/osrelease file.
#!/bin/bash
if uname -r |grep -q 'Microsoft' ; then
echo True
fi
if grep -q -i 'Microsoft' /proc/version ; then
echo True
fi
if grep -q -i 'Microsoft' /proc/sys/kernel/osrelease ; then
echo True
fi
Also there are many file existence can be checked with shell script. For example, only WSL has 1. /dev/lxss 2. /bin/wslpath 3. /sbin/mount.drvfs 4. /proc/sys/fs/binfmt_misc/WSLInterop 5. /etc/wsl.conf files but GNU/Linux distributions has not.
See more:
screenFetch
netfetch
In WSL, there is a special file for checking interoperability called /proc/sys/fs/binfmt_misc/WSLInterop which is WSL specific file. You can check using the following command:
#!/bin/bash
if [ -f /proc/sys/fs/binfmt_misc/WSLInterop ]; then
echo True
fi
or more simple one-line code(in bash):
[ -f /proc/sys/fs/binfmt_misc/WSLInterop ]
This will return exit code 0 if true, exit code 1 if false.
Thanks to Biswapiryo's comment - I came up with this solution to detect WSL:
if [[ $(uname -r)] == ^*Microsoft$ ]]; then
# Code goes here
fi
Short/current answer:
To detect either WSL1 or WSL2, you can use a modified version of #MichaelSmith's answer:
#!/bin/zsh
if [[ $(uname -r) == (#s)*[mM]icrosoft*(#e) ]]; then
echo test
fi
More detail:
When this question was originally asked, only WSL1 existed, and uname -r would return something like:
4.4.0-22000-Microsoft
This is not a "real" kernel in WSL1, but just the number/name that Microsoft chooses to provide in response to that particular syscall. The 22000, in this case, is the Windows build number, which currently corresponds to the WSL release. Note that this is the case even in the current WSL Preview in the Microsoft Store, even though it is decoupled from the Windows release.
With WSL2, however, Microsoft provides a real Linux kernel, which returns something like:
5.10.102.1-microsoft-standard-WSL2
Earlier versions may have left off the -WSL2 portion.
Of course, if you build your own WSL2 kernel, you should update the test to match the kernel name you provide.

Detect IP-Address change on an interface

I would like to trigger a service when a change of an ip address on a specific interface occurs. Is there a target for this or some other method I am not aware of to achieve this using systemd on Linux (Kernel 3.19)?
The service would be used to send a SIGNAL to a defined process. The Linux is running on an embedded system.
Thanks!
Because you use Systemd you might already use systemd-networkd for managing your devices instead of relying on 3rd party code.
You could use the structured journal output to get the last 2 ADDRESS field of the current BOOD_ID.(sadly, there is no notification mechanism for address changes in systemd-networkd):
→ sudo journalctl -F ADDRESS -u systemd-networkd -n 2
192.168.178.29
So, if there is only one line output, there was no address change.
There is an solution in other question of StackOverflow. Just here:
Detecting a change of IP address in Linux
I like this code, it's easy, you onli need a cron job with frecuency as you need (I made a little change):
#!/bin/bash
OLD_IP=`cat ip.txt`
NEW_IP=`/sbin/ifconfig | awk -F "[: ]+'{ print $4}'`
if [ $NEW_IP != OLD_IP ]; then
YOU_COMMAND <commands>
echo $NEW_IP > ip.txt
fi
exit 0

Equivalent lsof -i in Solaris

I have a fast question. I want to know what is the losf -i equivalent command in a Solaris system.
I only want to show the files with network connection.
Thank you!!
Here is a shell script that list all processes having open TCP or UDP ports on Solaris, you can limit it to a given port number by passing it as an argument:
pfiles /proc/* 2>/dev/null | nawk -v port=$1 '
/^[0-9]/ { cmd=$2; type="unknown"; continue }
$1 == "SOCK_STREAM" { type="tcp" }
$1 == "SOCK_DGRAM" { type="udp" }
$2 ~ "AF_INET" { if((port!="")&&($5!=port)) continue;
if(cmd!="") { printf("%s\n",cmd); cmd="" }
printf(" %s:%s/%s\n",$3,$5,type); }'
Note: As documented in the warning section of the pfiles manual page, it is not recommended to run this command on a heavily loaded production system with a time sensitive process running as deadlocks or crashes might happen.
Note #2: The previous warning doesn't apply to the last update of Solaris (Oracle Solaris 11.4) because pfiles no more suspend the monitored process(es). It now just uses ad hoc /proc pseudo files.
As of Solaris 11.2 this type of information is now available directly in the netstat command (-u option) so you don't have to use the pfiles hack for the purpose or use the lsof tool. Personally I've always wondered why this information could not be part of the netstat output so glad to see that'll finally be the case.
There's a nice blog from Oracle on the topic.
(caveat: at the time of writing v11.2 is in beta but fully disclosed as to the contents / new features)
you can try pfiles,fuser. you can install lsof on solaris.
http://andriigrytsenko.net/2010/08/lsof-installation-on-solaris-10/

Searching for function in bash script to detect installed software packages

I need some code which checks, if a list of packages is installed. This check should work on each linux distribution (Fedora, Arch-Linux, Debian, RedHat,...).
Actually is my script looking like that:
#!/bin/bash
# At first check, if all needed softwares are installed
declare -a NEEDED_SOFTWARE_LIST=(bash rsync wget grep telnet)
if [ -f /etc/debian_version ]; then
for SOFTWARE in ${NEEDED_SOFTWARE_LIST[#]}; do
dpkg -l | grep -i $SOFTWARE | head -1 | if [[ "$(cut -d ' ' -f 1)" != "ii" ]]; then
echo -e "$SOFTWARE is NOT installed completely! Please install it...\n";
exit 1;
fi
done
else
echo "No Debian";
fi
I hope somebody can help me.
when you say:
This check should work on each linux distribution (Fedora, Arch-Linux, Debian, RedHat,...).
You are close to hell....
There is no easy way to do it with confidence in all distros.
with this approach, you will find that:
there is no reliable way to guess the distro, it depends even from version to version...
there is no reliable way to say "this package is not in the system", you will just assume that if its not installed using that distro's official package manager, it wont be there.
sometimes, people use more than just one package manager.
there is no reliable way to know if the package that you are talking about, has that name in that distro (e.g. - php can be "php" in one distro, "php5" in another one, and both are "php5").
this will become a hard to maintain, easy to fail, never reliable, piece of software.
so if you need to create an installer, and have dependencies, please, use a well known package manager, build a good package, and dont re-invent the wheel.
It might sound daunting, but it will pay off on the long run.
Wouldn't it be simpler to just check that the binary is found?
declare -a NEEDED_SOFTWARE_LIST=(bash rsync wget grep telnet)
for SOFTWARE in ${NEEDED_SOFTWARE_LIST[#]} ; do
$SOFTWARE --version |& grep "command not found" && echo "$SOFTWARE is NOT installed completely! Please install it..." && exit 1
done

killproc and pidofproc on linux

I have a script which uses killproc and procofpid commands and executes fine on a 64bit suse. But when I executed the script on 32bit redhat , I found that the above commands donot exist.
I don't have a 32bit Suse and 64bit redhat machines to test my script.
Is my guess right that on 64bit redhat the above commands should be available?
Or are the above commands specific to Suse and redhat?
Thanks
killproc is in redhat enterprise linux 5.4 as part of /etc/init.d/functions
if you need it just do
. /etc/init.d/functions
in your script to load the shell functions, its probably in other versions of redhat but thats the only one i have to hand at the moment
These commands are defined as part of the Linux Standards Base (LSB), as noted by #AndreKR.
However, on some systems like Redhat (and probably SUSE), depending on packages installed, these functions may not be defined in the location specified by the LSB, which is /lib/lsb/init-functions. Rather they are defined within /etc/init.d/functions. In addition, in some versions, the Redhat variant of /etc/init.d/functions is missing the LSB-defined function start_daemon. If you add the following snippet to the top of your script, it should be portable across most distributions/installs:
if [[ -f /lib/lsb/init-functions ]]; then
. /lib/lsb/init-functions
elif [[ -f /etc/init.d/functions ]]; then
. /etc/init.d/functions
# Pretend to be LSB-compliant
function start_daemon() {
daemon $*
}
else
echo "Linux LSB init function script or Redhat /etc/init.d/functions is required for this script."
echo "See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptfunc.html"
exit 1
fi
The commands are unlikely to be portable. Actually this is first time I hear about them - but I guess your problem is to work with process by the name, not pid.
Check the man pgrep or man pkill - they are slightly bit more portable. They are part of procps package (where ps and top come from) and should be available on all Linux variants. They are also available on Solaris.
The ones used in Ubuntu are part of the specification "Linux Standard Base" and are documented there.
I think those commands are distrib specifics: I have never seen them before.
killproc should be a kind of kill but what is procofpid supposed to do?
In the title you speak about pidofproc, you can find this command under the pidof on most linux boxes.
I had the same problem as you, it gave the warning:
pidof: invalid options on command line!
I changed the
"killproc -d 10 $cmd"
to
"kill -9 \`pidof $cmd\`"

Resources