Bash - how to check if packages can be installed, if apt-get/dpkg is running? - apt-get

In a bash script I want to install a package. Before sanely doing so, I need to check if no other instance of apt-get or dpkg is already working. If that was the case, the apt-get would fail, because its already locked.
Is it sufficient to check if /var/lib/dpkg/lock and /var/lib/apt/lists/lock exists and if both don't exist, installing is safe?

In Debian Wheezy (currently stable), those files always exist. Therefore I found using lsof /var/lib/dpkg/lock to be a more useful check. It returns 1 if nothing is using the lock, 0 if it is, so:
lsof /var/lib/dpkg/lock >/dev/null 2>&1
[ $? = 0 ] && echo "dpkg lock in use"

Checking lock files is insufficient and unreliable. Perhaps what you really want to do is to check whether dpkg database is locked. I do it using the following approach:
## check if DPKG database is locked
dpkg -i /dev/zero 2>/dev/null
if [ "$?" -eq 2 ]; then
echo "E: dpkg database is locked."
fi
Hopefully there is a better way...
Besides I also do the following check as it might be unsafe to install if there are broken packages etc.:
apt-get check >/dev/null 2>&1
if [ "$?" -ne 0 ]; then
echo "E: \`apt-get check\` failed, you may have broken packages. Aborting..."
fi

You can simply check if apt-get or dpkg are running:
ps -C apt-get,dpkg >/dev/null && echo "installing software" || echo "all clear"

It depends how well you want to handle apt-get errors.
For your needs checking /var/lib/dpkg/lock and /var/lib/apt/lists/lock is fine, but if you want to be extra cautious you could do a simulation and check the return code, like this:
if sudo apt-get --simulate install packageThatDoesntExist
then echo "we're good"
else echo "oops, something happened"
fi
Which will give for instance:
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package packageThatDoesntExist
oops, something happened
Edit: --simulate will not check for locks, so you might want to do an additional check there. You might also want to remove sudo, if you want to check for sudo separately.

Related

bash script for install mysql and configure it

Is it possible to create a simple script in bash for install mysql and for answer (in automatic) at the instruction mysql_secure_installation?
Because I have created a script for install in bash
#!/bin/bash
if [[ $UID != 0 ]]; then
echo "Please run this script with sudo:"
echo "sudo $0 $*"
exit 1
fi
sudo apt-get -y install mysql-server
But how is it possible specify at command sudo mysql_secure_installation the answers to the questions it proposes? Thanks.

Fedora26 Systemd script not get executed

I created a simple systemd unit file(sysupdate.service) with following content to automate system updates, but got frustrated by complexity.
/etc/systemd/system/sysupdate.service:
[Unit]
Description=update system preferably after dnfdragora finished checking update
After=syslog.target network.target network-online.target auditd.service
[Service]
StandardInput=null
ExecStart=/mnt/0/sysupdate.sh
[Install]
WantedBy=multi-user.target
sysupdate.sh:
#!/bin/sh
exec &>> /mnt/0/sysupdate.log
echo $(date)
sudo dnf upgrade -y
echo '$?':$?
sudo youtube-dl -U
echo '$?':$?
sudo systemctl stop bluetooth.service
sudo systemctl disable bluetooth.service
sudo systemctl status bluetooth.service
echo '$?':$?
echo $(date)
The normal user has write privilege inside /mnt/0/.
sysupdate.sh was set "chmod uo+x".
Every time I commented out "service Type", "After" or "user" in service file, I always do:
sudo systemctl daemon-reload
The expected log file "/mnt/0/sysupdate.log" never gets created.
Why such simple automation is so difficult to get done?!
Latest status:
Even I executed as root the 2 lines of code given by "journalctl -xe":
SELinux is preventing (pdate.sh) from execute access on the file sysupdate.sh.
***** Plugin catchall (100. confidence) suggests **************************
If you believe that (pdate.sh) should be allowed execute access on the sysupdate.sh file by defa
Then you should report this as a bug.
You can generate a local policy module to allow this access.
Do
allow this access for now by executing:
# ausearch -c '(pdate.sh)' --raw | audit2allow -M my-pdatesh
# semodule -X 300 -i my-pdatesh.pp
There's still permission denied error in journal log.
I temporarily got it work by setting SELinux permissive.

"Wrong sources.list entry or malformed file" for Chrome while using `apt-get update`

I am trying to use sudo apt-get update But i am getting error as,
W: Failed to fetch http://dl.google.com/linux/chrome/deb/dists/stable/Release Unable to find expected entry 'main/binary-i386/Packages' in Release file (Wrong sources.list entry or malformed file)
E: Some index files failed to download. They have been ignored, or old ones used instead.
I tired the solution given in https://askubuntu.com/questions/120621/how-to-fix-duplicate-sources-list-entry, but again showing the same error. Suggest me something.
It looks like Google has discontinued support for i386, which is why this error now shows up. It looks like they have not gracefully for how their deb install has configured apt. To fix this run the following.
sudo sed -i -e 's/deb http/deb [arch=amd64] http/' "/etc/apt/sources.list.d/google-chrome.list"
Source: https://www.reddit.com/r/chrome/comments/48oje6/linux_how_to_fix_failed_to_fetch/
Edit: As has been pointed out by others, another command is needed to prevent this fix from reverting. Since this is at the top as the accepted answer I feel it should be part of this answer.
sudo sed -i -e 's/deb http/deb [arch=amd64] http/' "/opt/google/chrome/cron/google-chrome"
Also, this issue may exist if there are two files with name google.list and google-chrome.list in /etc/apt/sources.list.d directory with the similar entry like:
In google.list:
deb http://dl.google.com/linux/chrome/deb/ stable main
In google-chrome.list:
deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main
Then you should remove google.list file or uncomment its entry like below:
#deb http://dl.google.com/linux/chrome/deb/ stable main
That change was reverting overnight for me. Apparently you also need to change /opt/google/chrome/cron/google-chrome
sudo sed -i -e 's/deb http/deb [arch=amd64] http/' "/opt/google/chrome/cron/google-chrome"
Note: this is only for 64-bit
Source: further down that same Reddit thread and http://www.webupd8.org/2016/03/fix-failed-to-fetch-google-chrome_3.html
This doesn't work because there is a default config in /etc/default/google-chrome that contains instructions on repository updating. If you open the google-chrome.list file in /etc/apt/sources.list.d/ you will see that it has the comment:
### THIS FILE IS AUTOMATICALLY CONFIGURED ###
# You may comment out this entry, but any other modifications may be lost.
Like the note says, the changes using the instructions in the previous comments will probably be overwritten the next time you update. To resolve this, do the following:
Open a terminal and run cd /etc/default , then sudo nano google-chrome (Note: you can use whatever editor you wish of course))
In the config file, change the 2nd line: repo_reenable_on_distupgrade="true" so that it is false, as in
repo_reenable_on_distupgrade="false", then save the config file.
Now, you can make the edit to the repo as instructed above. In a terminal window run the commands as shown in the previous comments:
sudo sed -i -e 's/deb http/deb [arch=amd64] http/' "/etc/apt/sources.list.d/google-chrome.list"
sudo sed -i -e 's/deb http/deb [arch=amd64] http/' "/opt/google/chrome/cron/google-chrome"
You changes now won't be overwritten by the config directive.
PS. This works in Linux Mint 17.3 so it will probably work in Ubuntu and any Ubuntu based distro as well.
Go to "Software Sources" section in Ubuntu Settings then click on "other software" tab then uncheck: http://dl.google.com/linux/chrome/deb/stable
Now sudo apt-get update will work.
After updating manager go and undo the changes in software sources.
I solved this problem by following process:
1.Open a new Terminal window and run the following command:
sudo gedit /etc/apt/sources.list.d/google-chrome.list
2.In the text file that opens edit the file so that the line reads:
deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main
N.B: The only addition you need to make is entering the [amd64] architecture after ‘deb’ but preceding the ‘http’. Do not edit or replace any other text in this file.
3.Hit Save. Close the Gedit window and return to the Terminal and refresh your package list by runnin
sudo apt-get update
The ‘failed to fetch’ APT error should no longer appear.
source link
This didn't work for me, until I modified yet another file:
/etc/apt/sources.list.d/additional-repositories.list
and changed:
deb http://dl.google.com/linux/chrome/deb/ stable main
to
deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main

apt-get update fails to update mysql

Whenever I run sudo apt-get update in Ubuntu 14.04.2 I keep getting this message at the end. I've just been ignoring it but I'm worried that I'm not getting all of the updates I should because of it. How should I fix this?
W: Failed to fetch http://repo.mysql.com/apt/ubuntu/dists/trusty/InRelease Unable to find expected entry 'utilities-1.4/binary-amd64/Packages' in Release file (Wrong sources.list entry or malformed file)
$ sudo dpkg-reconfigure mysql-apt-config
Connector-Python >> connector-python-2.0 >> Apply
$ sudo apt-get update
In my case I had to remove the repository "https://repo.mysql.com/apt/ubuntu focal mysql-apt-config".
Software & Updates -> Other Software -> select it, and remove it or uncheck it.

How to download all dependencies and packages to directory

I'm trying to install a package on a machine with no Internet connection. What I want to do is download all the packages and dependences on a machine WITH an Internet connection and then sneaker-net everything to the offline computer.
I've been playing with the apt-get and apt-cache but I haven't figured out a quick and easy way to download the package and dependencies in one swoop to a directory of my choosing. How would I do this? Am I going about this problem correctly?
How would you install offline packages that have a lot of dependencies?
The marked answer has the problem that the available packages on the machine that is doing the downloads might be different from the target machine, and thus the package set might be incomplete.
To avoid this and get all dependencies, use the following:
apt-get download $(apt-rdepends <package>|grep -v "^ ")
Some packages returned from apt-rdepends don't exist with the exact name for apt-get download to download (for example, libc-dev). In those cases, filter out those exact names (be sure to use ^<NAME>$ so that other related names, for example libc-dev-bin, that do exist are not skipped).
apt-get download $(apt-rdepends <package>|grep -v "^ " |grep -v "^libc-dev$")
Once downloaded, you can move the .deb files to a machine without Internet and install them:
sudo dpkg -i *.deb
Same question already answered here:
How to list/download the recursive dependencies of a debian package?
try:
PACKAGES="wget unzip"
apt-get download $(apt-cache depends --recurse --no-recommends --no-suggests \
--no-conflicts --no-breaks --no-replaces --no-enhances \
--no-pre-depends ${PACKAGES} | grep "^\w")
# aptitude clean
# aptitude --download-only install <your_package_here>
# cp /var/cache/apt/archives/*.deb <your_directory_here>
The aptitude --download-only ... approach only works if you have a debian distro with internet connection in your hands.
If you don't, I think it is better to run the following script on the disconnected debian machine:
apt-get --print-uris --yes install <my_package_name> | grep ^\' | cut -d\' -f2 >downloads.list
move the downloads.list file into a connected linux (or non linux) machine, and run:
wget --input-file myurilist
this downloads all your files into the current directory.After that you can copy them on an USB key and install in your disconnected debian machine.
Credits: http://www.tuxradar.com/answers/517
This will download all the Debs to the current directory, and will NOT fail if It can't find a candidate.
Also does NOT require sudo to run sript!
nano getdebs.sh && chmod +x getdebs.sh && ./getdebs.sh
#!/bin/bash
package=ssmtp
apt-cache depends "$package" | grep Depends: >> deb.list
sed -i -e 's/[<>|:]//g' deb.list
sed -i -e 's/Depends//g' deb.list
sed -i -e 's/ //g' deb.list
filename="deb.list"
while read -r line
do
name="$line"
apt-get download "$name"
done < "$filename"
apt-get download "$package"
Note: I used this as my example because I was actually trying to DL the Deps for SSMTP and it failed on debconf-2.0, but this script got me what I need!
Somewhat simplified (and what worked for me) way that worked for me (based on all the above)
Note that dependencies hierarchy can go deeper then one level
Get dependencies of your package
$ apt-cache depends mongodb | grep Depends:
Depends: mongodb-dev
Depends: mongodb-server
Get urls:
sudo apt-get --print-uris --yes -d --reinstall install mongodb-org mongodb-org-server mongodb-org-shell mongodb-org-tools | grep "http://" | awk '{print$1}' | xargs -I'{}' echo {} | tee files.list
wget --input-file files.list
I used apt-cache depends package to get all required packages in any case if the are already installed on system or not.
So it will work always correct.
Because the command apt-cache works different, depending on language, you have to try this command on your system and adapt the command.
apt-cache depends yourpackage
On an englisch system you get:
$ apt-cache depends yourpackage
node
Depends: libax25
Depends: libc6
On an german system you get:
node
Hängt ab von: libax25
Hängt ab von: libc6
The englisch version with the term:
"Depends:"
You have to change the term "yourpackage" to your wish twice in this command, take care of this!
$ sudo apt-get --print-uris --yes -d --reinstall install yourpackage $(apt-cache depends yourpackage | grep " Depends:" | sed 's/ Depends://' | sed ':a;N;$!ba;s/\n//g') | grep ^\' | cut -d\' -f2 >downloads.list
And the german version with the term:
"Hängt ab von:"
You have to change the term "yourpackage" to your wish twice in this command, take care of this!
This text is used twice in this command, if you want to adapt it to your language take care of this!
$ sudo apt-get --print-uris --yes -d --reinstall install yourpackage $(apt-cache depends yourpackage | grep "Hängt ab von:" | sed 's/ Hängt ab von://' | sed ':a;N;$!ba;s/\n//g') | grep ^\' | cut -d\' -f2 >downloads.list
You get the list of links in downloads.list
Check the list, go to your folder and run the list:
$ cd yourpathToYourFolder
$ wget --input-file downloads.list
All your required packages are in:
$ ls yourpathToYourFolder
This will download all packages and dependencies (no already installed) to a directory of your choice:
sudo apt-get install -d -o Dir::Cache=/path-to/directory/apt/cache -o Dir::State::Lists=/path-to/directory/apt/lists packages
Make sure /path-to/directory/apt/cache and /path-to/directory/apt/lists exist.
If you don't set -o Dir::Cache it points to /var/cache/apt,
Dir::State::Lists points to /var/lib/apt/lists (which keeps the index files of available packages)
Both -o options can be used with update and upgrade instead of install.
On different machine run the same command without '-d'
I'm assuming you've got a nice fat USB HD and a good connection to the net. You can use apt-mirror to essentially create your own debian mirror.
http://apt-mirror.sourceforge.net/
On modern Ubuntu systems (for example, 22.04):
apt clean
apt update
apt install --download-only freeipa-client
After you can find deb-files in
ls -l /var/cache/apt/archives/
IF you accept the caveat that there may be dependencies already installed on your system, then the easiest way is to go apt-get install --simulate <your_package>, this will first list all the deps it will install, then copy the list of packages, then apt-get download <the_list_of_packages>
e.g. for qt5-gtk2-platformtheme on a xubuntu-21.04 MINIMAL INSTALL you'll get (after apt-get install --simulate) the following:
libdouble-conversion3 libmd4c0 libpcre2-16-0 libqt5core5a libqt5dbus5 libqt5gui5 libqt5network5 libqt5svg5 libqt5widgets5 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xinerama0 libxcb-xinput0 libxcb-xkb1 libxkbcommon-x11-0 qt5-gtk-platformtheme qttranslations5-l10n
then you just cd in a folder of your choice, do apt-get download <the_list_above>, and you have them all d/w in there. you can then dpkg -i *.deb
Complementing and automating the exclusion of ALL conflictive dependencies (dependencies not found) by the command given by #onno:
apt-get download $(apt-rdepends <package>|grep -v "^ " |grep -v "^conflictiv-dependency$")
At least for Ubuntu, where the Error Message format is as follows:
E: Can't select candidate version from package <package> as it has no candidate
The following script Downloads all Found Dependencies, Excluding not Found ones:
#!/bin/bash
rm -f error.txt
apt download $(apt-rdepends $1 | grep -v "^ ") 2> error.txt
#IF THERE WAS ERRORS (DEPENDENCIES NOT FOUND)
if [ $(cat error.txt | wc -l) -gt 0 ]
then
partial_command="\("
while read -r line
do
conflictive_package="$(awk '{split($0,array," "); print array[8]}' <<< $line)"
partial_command="$partial_command$conflictive_package\|"
done < error.txt
partial_command="$(awk '{print substr($0, 1, length($0)-2)}' <<< $partial_command)\)"
eval "apt download \$(apt-rdepends $1 | grep -v '^ ' | grep -v '^$partial_command$')"
fi
rm error.txt
It works with me
sudo apt-get reinstall --download-only <your software>
for example
sudo apt-get reinstall --download-only ubuntu-restricted-extras
For accessing installed .deb files, you can look in this path:
/var/cache/apt/archives