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\`"
Related
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.
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.
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
I am coding on a Red Hat Machine and I want to get the process id of a process in the interactive mode as well as the in a script.
In bash 'pidof' works but not in zsh.
What would be the equivalent of pidof in zsh ?
Thank you in advance.
You may wish to which pidof in bash, to determine the location of pidof and then try running zsh with the absolute path.
If the above works, you just have a $PATH issue (as I have never seen pidof as a bash builtin.)
If that doesn't work try the following:
This is probably not a simple as you want, but it works for me:
pgrep -U $USER some_program
Where 'some_program' is the name you would normally supply pidof.
On a RHEL (Red Hat Enterprise Linux) machine pidof is located at /sbin/pidof. Just add /sbin to your path.
I have several init.d scripts that I'm using to start some daemons. Most of these scripts I've found on the internet and they all use start-stop-daemon. My understanding is that "start-stop-daemon" is a command that is specific to Linux or BSD distros and is not available on Solaris.
What is the best way to translate my init.d scripts from Linux to Solaris? Is there a command equivalent to start-stop-daemon that I can use, roughly?
Since I'm not much of a Solaris user, I'm willing to admit upfront that I don't even know if my question is inherently invalid or not.
start-stop-daemon is a Linux thing, and not used that much on Solaris. I guess you can port the command though, if you want to reuse your init scripts.
Otherwise it depends on what version of Solaris you are using. Starting with Solaris 10 and also OpenSolaris they use a new startup script framework "Solaris Service Management Facility", which you configure with the commands svcs, svccfg and svcadm.
See http://www.oracle.com/technetwork/server-storage/solaris/overview/servicemgmthowto-jsp-135655.html for more information.
For older Solaris releases most init scripts are written in pure shell without any helper commands like start-stop-daemon.
On Solaris 10 or later using SMF is recommended, but on an earlier release you'd create an init script in /etc/init.d and link to it from the rcX.d directories. Here's a bare-bones example of an init script for launching an rsync daemon:
#!/sbin/sh
startcmd () {
/usr/local/bin/rsync --daemon # REPLACE WITH YOUR COMMANDS
}
stopcmd () {
pkill -f "/usr/local/bin/rsync --daemon" # REPLACE WITH YOUR COMMANDS
}
case "$1" in
'start')
startcmd
;;
'stop')
stopcmd
;;
'restart')
stopcmd
sleep 1
startcmd
;;
*)
echo "Usage: $0 { start | stop | restart }"
exit 1
;;
esac
Create a link to the script from each rcX.d directory (following the "S"/"K" convention).
ln rsync /etc/rc3.d/S91rsync
for i in `ls -1d /etc/rc*.d | grep -v 3`; do ln rsync $i/K02rsync; done
See the README in each rcX.d directory and check the man page for init.d. Here's a bit of the man page:
File names in rc?.d directories are of the form
[SK]nn, where S means start this job, K means
kill this job, and nn is the relative sequence number for killing or
starting the job.
When entering a state (init S,0,2,3,etc.) the rc[S0-6] script
executes those scripts in /etc/rc[S0-6].d that are prefixed with K
followed by those scripts prefixed with S. When executing each
script in one of the /etc/rc[S0-6] directories, the /sbin/rc[S0-6]
script passes a single argu- ment. It passes the argument 'stop'
for scripts prefixed with K and the argument 'start' for scripts
prefixed with S. There is no harm in applying the same sequence
number to multiple scripts.