Checking if software is installed in SSH session - linux

I am trying to check whether a certain package is installed on remote machine in bash script.
If I execute the following statement on the machine itself the result is 1 (installed) in file check.txt, which is correct:
dpkg-query -W -f='${Status}' nano 2>/dev/null | grep -c "ok installed" > /home/someuser/check.txt
However, if I execute the same command in SSH session, the result is always 0.
Can somebody explain why and how to correct this?
Thank you.
#!/bin/bash
ADDRESS=SOMEUSER#$SOMESERVER
function run {
ssh $ADDRESS /bin/bash $#
}
run << SSHCONNECTION
dpkg-query -W -f='${Status}' nano 2>/dev/null | grep -c "ok installed" > /home/someuser/check.txt
SSHCONNECTION

You need to escape the $ character:
dpkg-query -W -f='\${Status}' nano 2>/dev/null | grep -c "ok installed" > /home/someuser/check.txt

Related

OpenBSD 6.7 how to install xbase

I am updating our integration test environments to OpenBSD 6.7 (from 6.5)
We use ansible to install all the packages on the target system (openbsd 6.7, Vagrant image https://app.vagrantup.com/generic/boxes/openbsd6/versions/3.0.6 )
With the above image, I cannot install java openjdk 11.
obsd-31# pkg_add -r jdk%11
quirks-3.325 signed on 2020-05-27T12:56:02Z
jdk-11.0.7.10.2p0v0:lz4-1.9.2p0: ok
jdk-11.0.7.10.2p0v0:zstd-1.4.4p1: ok
jdk-11.0.7.10.2p0v0:jpeg-2.0.4p0v0: ok
jdk-11.0.7.10.2p0v0:tiff-4.1.0: ok
jdk-11.0.7.10.2p0v0:lcms2-2.9p0: ok
jdk-11.0.7.10.2p0v0:png-1.6.37: ok
jdk-11.0.7.10.2p0v0:giflib-5.1.6: ok
Can't install jdk-11.0.7.10.2p0v0 because of libraries
|library X11.17.0 not found
| not found anywhere
|library Xext.13.0 not found
| not found anywhere
|library Xi.12.1 not found
| not found anywhere
|library Xrender.6.0 not found
| not found anywhere
|library Xtst.11.0 not found
| not found anywhere
|library freetype.30.0 not found
| not found anywhere
Direct dependencies for jdk-11.0.7.10.2p0v0 resolve to png-1.6.37 libiconv-1.16p0 giflib-5.1.6 lcms2-2.9p0 jpeg-2.0.4p0v0
Full dependency tree is giflib-5.1.6 lz4-1.9.2p0 tiff-4.1.0 png-1.6.37 xz-5.2.5 jpeg-2.0.4p0v0 lcms2-2.9p0 zstd-1.4.4p1 libiconv-1.16p0
Couldn't install jdk-11.0.7.10.2p0v0
my guess is that xbase is not installed.
However, I cannot figure out how to install xbase without rebooting into a bootable installer (because I need to do it via a shell command running from ansible)
Is there a way?
The generic OpenBSD Vagrant image you're using was created as a command line environment, so the X windows files were were excluded during the install process.
There are lots of ways to add X windows to OpenBSD after installation, but the quickest method that comes to mind would be:
sudo su -l
curl -LO 'https://ftp.usa.openbsd.org/pub/OpenBSD/6.7/amd64/x{base,serv,font,share}67.tgz'
tar xzf xbase67.tgz -C /
tar xzf xserv67.tgz -C /
tar xzf xfont67.tgz -C /
tar xzf xshare67.tgz -C /
rm -f xbase67.tgz xfont67.tgz xserv67.tgz xshare67.tgz
ldconfig /usr/local/lib /usr/X11R6/lib
If you would like to test for the presence of X windows on OpenBSD, try using the following shell snippet:
if [ -d /usr/X11R6/bin/ ] && [ -f /usr/X11R6/bin/xinit ]; then
echo "X windows has been installed."
else
echo "This is a command line only system."
fi
The xbase file set can be extracted manually via the following commands:
cd /
curl -LO https://ftp.usa.openbsd.org/pub/OpenBSD/6.7/amd64/xbase67.tgz
tar xzvf xbase67.tgz
Note: this is the mirror used in the vagrant sources.
If you care about security enough to use OpenBSD, then you really shouldn't grab new package sets from the internet without also checking the hashes/signatures are valid. Try this script:
#!/bin/ksh
echo -n "Downloading ... "
curl --silent --fail --fail-early -O "https://ftp.usa.openbsd.org/pub/OpenBSD/7.0/amd64/SHA256.sig" -O "https://ftp.usa.openbsd.org/pub/OpenBSD/7.0/amd64/x{base,font,serv,share}70.tgz"
if [ $? != 0 ]; then
echo "X windows download failed. Terminating."
exit 1
fi
echo "complete."
signify -Cp /etc/signify/openbsd-70-base.pub -x SHA256.sig xbase70.tgz xfont70.tgz xserv70.tgz xshare70.tgz
if [ $? != 0 ]; then
echo "X windows signature verification failed. Terminating."
exit 1
fi
tar -z -x -C / -f xbase70.tgz && tar -z -x -C / -f xfont70.tgz && tar -z -x -C / -f xserv70.tgz && tar -z -x -C / -f xshare70.tgz
if [ $? != 0 ]; then
echo "X windows installation failed. Terminating."
exit 1
fi
echo "Installation complete. Happy hacking."
On the other hand if you just want a one liners:
# Install just x11 base set.
sudo ksh -c 'curl --silent https://ftp.usa.openbsd.org/pub/OpenBSD/7.0/amd64/xbase70.tgz | gzip -d -c | tar -x -C / -f - '
# Install all the x11 sets.
sudo ksh -c 'curl --silent https://ftp.usa.openbsd.org/pub/OpenBSD/7.0/amd64/xbase70.tgz | gzip -d -c | tar -x -C /-f - '
You can omit the sudo portion if you are already logged in as root. And for the vagrant folks, the lazy version looks:
# Install just x11 base set from the host, to a vagrant guest.
vagrant ssh -c "sudo ksh -c 'curl --silent https://ftp.usa.openbsd.org/pub/OpenBSD/7.0/amd64/xbase70.tgz | gzip -d -c | tar -x -C / -f - '"
# Install all the x11 sets from the host, to a vagrant guest.
vagrant ssh -c "sudo ksh -c 'curl --silent -O \"https://ftp.usa.openbsd.org/pub/OpenBSD/7.0/amd64/x{base,font,serv,share}70.tgz\" && tar -z -x -C / -f xbase70.tgz && tar -z -x -C / -f xfont70.tgz && tar -z -x -C / -f xserv70.tgz && tar -z -x -C / -f xshare70.tgz'"

How to restrict output in shell script of a command executing in loop

I'm having a shell script as follows
#!/usr/bin/env bash
#Packages list
declare -a packages=( git build_essential node )
declare -a packages_status
# installing=`apt-get install -y `
installing="echo "
for i in "${packages[#]}"
do
packages_status[$i]=$(dpkg-query -W -f='${status}' $i | grep "install ok installed")
# echo ${packages_status[$i]}
done
The line of code
packages_status[$i]=$(dpkg-query -W -f='${status}' $i | grep "install ok installed")
produces the following output
dpkg-query: no packages found matching build_essential
dpkg-query: no packages found matching node
I want that LOC to execute without producing any output.
dpkg-query command ouputs errors to stderr, not stdout.
So, you should link the two channels before piping to grep:
packages_status[$i]=$(dpkg-query -W -f='${status}' $i 2>&1 | grep "install ok installed")
This way the script will only print lines "install ok installed" for installed packages.
In order not to see error output, you can redirect that output (stream number 2) to the NULL device:
Do_Whatever 2>/dev/null
In order not to see any output, you can redirect normal output (stream number 1) to the NULL device and redirect error output there too:
Do_Whatever >/dev/null 2>&1

Changing msg_max size on Linux [duplicate]

This question already has answers here:
How do I use sudo to redirect output to a location I don't have permission to write to? [closed]
(15 answers)
Closed 1 year ago.
This is a pretty simple question, at least it seems like it should be, about sudo permissions in Linux.
There are a lot of times when I just want to append something to /etc/hosts or a similar file but end up not being able to because both > and >> are not allowed, even with root.
Is there someway to make this work without having to su or sudo su into root?
Use tee --append or tee -a.
echo 'deb blah ... blah' | sudo tee -a /etc/apt/sources.list
Make sure to avoid quotes inside quotes.
To avoid printing data back to the console, redirect the output to /dev/null.
echo 'deb blah ... blah' | sudo tee -a /etc/apt/sources.list > /dev/null
Remember about the (-a/--append) flag!
Just tee works like > and will overwrite your file. tee -a works like >> and will write at the end of the file.
The problem is that the shell does output redirection, not sudo or echo, so this is being done as your regular user.
Try the following code snippet:
sudo sh -c "echo 'something' >> /etc/privilegedfile"
The issue is that it's your shell that handles redirection; it's trying to open the file with your permissions not those of the process you're running under sudo.
Use something like this, perhaps:
sudo sh -c "echo 'something' >> /etc/privilegedFile"
sudo sh -c "echo 127.0.0.1 localhost >> /etc/hosts"
Doing
sudo sh -c "echo >> somefile"
should work. The problem is that > and >> are handled by your shell, not by the "sudoed" command, so the permissions are your ones, not the ones of the user you are "sudoing" into.
I would note, for the curious, that you can also quote a heredoc (for large blocks):
sudo bash -c "cat <<EOIPFW >> /etc/ipfw.conf
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<plist version=\"1.0\">
<dict>
<key>Label</key>
<string>com.company.ipfw</string>
<key>Program</key>
<string>/sbin/ipfw</string>
<key>ProgramArguments</key>
<array>
<string>/sbin/ipfw</string>
<string>-q</string>
<string>/etc/ipfw.conf</string>
</array>
<key>RunAtLoad</key>
<true></true>
</dict>
</plist>
EOIPFW"
In bash you can use tee in combination with > /dev/null to keep stdout clean.
echo "# comment" | sudo tee -a /etc/hosts > /dev/null
Some user not know solution when using multiples lines.
sudo tee -a /path/file/to/create_with_text > /dev/null <<EOT
line 1
line 2
line 3
EOT
Using Yoo's answer, put this in your ~/.bashrc:
sudoe() {
[[ "$#" -ne 2 ]] && echo "Usage: sudoe <text> <file>" && return 1
echo "$1" | sudo tee --append "$2" > /dev/null
}
Now you can run sudoe 'deb blah # blah' /etc/apt/sources.list
Edit:
A more complete version which allows you to pipe input in or redirect from a file and includes a -a switch to turn off appending (which is on by default):
sudoe() {
if ([[ "$1" == "-a" ]] || [[ "$1" == "--no-append" ]]); then
shift &>/dev/null || local failed=1
else
local append="--append"
fi
while [[ $failed -ne 1 ]]; do
if [[ -t 0 ]]; then
text="$1"; shift &>/dev/null || break
else
text="$(cat <&0)"
fi
[[ -z "$1" ]] && break
echo "$text" | sudo tee $append "$1" >/dev/null; return $?
done
echo "Usage: $0 [-a|--no-append] [text] <file>"; return 1
}
You can also use sponge from the moreutils package and not need to redirect the output (i.e., no tee noise to hide):
echo 'Add this line' | sudo sponge -a privfile
By using sed -i with $ a , you can append text, containing both variables and special characters, after the last line.
For example, adding $NEW_HOST with $NEW_IP to /etc/hosts:
sudo sed -i "\$ a $NEW_IP\t\t$NEW_HOST.domain.local\t$NEW_HOST" /etc/hosts
sed options explained:
-i for in-place
$ for last line
a for append
echo 'Hello World' | (sudo tee -a /etc/apt/sources.list)
How about:
echo text | sudo dd status=none of=privilegedfile
I want to change /proc/sys/net/ipv4/tcp_rmem.
I did:
sudo dd status=none of=/proc/sys/net/ipv4/tcp_rmem <<<"4096 131072 1024000"
eliminates the echo with a single line document
This worked for me:
original command
echo "export CATALINA_HOME="/opt/tomcat9"" >> /etc/environment
Working command
echo "export CATALINA_HOME="/opt/tomcat9"" |sudo tee /etc/environment
Can you change the ownership of the file then change it back after using cat >> to append?
sudo chown youruser /etc/hosts
sudo cat /downloaded/hostsadditions >> /etc/hosts
sudo chown root /etc/hosts
Something like this work for you?

lpr command not working with CYGWIN.

#!/bin/bash
while :
do
if [ -e ./*.pdf ]
then
#printer=$(lpstat -p | grep printer | head -n1 | cut -d \ -f 2)
printer=$(cat printer.ini)
for file in *.pdf
do
echo "Printing $file"
$(lpr -P $printer $file)
echo "Moving $file"
$(mv $file ./p)
done
fi
done
when I'm trying to run this script in windows using CYGWIN it is showing..lpr is not a internal or external command..Please give me a solution for this.
Cygwin has modules (packages). A limited amount of them are installed by default, you need to choose the ones you need by running the setup again and selecting them. lpr is in cygutils, iirc. Also, you seem to be running this in a windows command prompt instead of sh or mintty, etc. (error is specific to cmd.exe afaik).

ssh tunneled command output to file

I have an old Syno NAS and wish to use the "shred" command to wipe this disks inside. The idea is to let the command run to complete on the box itself without the need of a computer.
So far I have managed...
1) to get the right parameters for 'shred'
* runs in the background using the &
2) get that command to output the progress (-v option) to a file shred.txt
* to see from the file what the progress is
shred -v -f -z -n 2 /dev/hdd 2>&1 | tee /volume1/backup/shred.txt &
3) ssh tunnel the command so I can turn off my laptop while its running
ssh -n -f root#host "sh -c 'nohup /opt/bin/shred -f -z -n 2 /dev/sdd > /dev/null 2>&1 &'"
The problem is that I can't combine 2) and 3)
I tried to combine them like this, but the resulting file remained empty:
ssh -n -f root#host "sh -c 'nohup /opt/bin/shred -f -z -n 2 /dev/sdd 2>&1 | tee /volume1/backup/shred.txt > /dev/null &'"
It might be a case of the NOOBS but I can't figure out how to get this done.
Any suggestions?
Thanks. Vince
Commands sh and tee are not needed in here:
ssh -n root#host 'nohup /opt/bin/shred -f -z -n 2 /dev/sdd 2>&1 >/volume1/backup/shred.txt &' >/dev/null
The final >/dev/null is optional, it will just disregard any greetings from other hosts.
Tried the following command (based on Grzegorz suggestion) and included the opening date stamp and the before mentioned - stupidly forgotten - verbose switch. Last version of the command string:
ssh -n root#host 'date > /volume1/backup/shred_sda.txt; nohup /opt/bin/shred -v -f -z -n 4 /dev/sda 2>&1 >> /volume1/backup/shred_sda.txt # >/dev/null'
The last thing to figure out is how to include the date stamp when the shred command has completed.

Resources