0

I am writing a python script to get the apt-get command history with a date. Passing IP address and password as a parameter, then SSH into the host. In the command list, we have a list of Linux commands and execute these commands using for loop. Is there any command to get the last linux update date? I tried "history 5 | tail | grep 'apt-get update'" but python not able to print the output of this command.

import paramiko
import sys
hostname = sys.argv[1]
username = "root"
password = sys.argv[2]
commands = [
        "pwd",
        "history 5 | tail | grep 'apt-get update'",
        "ls -l /var/lib/apt/periodic/update-success-stamp | awk '{print $6" "$7" "$8}'",
        "tail -n 25 /var/log/apt/history.log"
]
# initialize the SSH client
client = paramiko.SSHClient()
# add to known hosts
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
    client.connect(hostname=hostname, username=username, password=password)
except:
    print("[!] Cannot connect to the SSH Server")
    exit()

# execute the commands
for command in commands:
    print("="*50, command, "="*50)
    stdin, stdout, stderr = client.exec_command(command)
    print(stdout.read().decode())
    err = stderr.read().decode()
    if err:
        print(err)
del stdin, stdout, stderr
1
  • I just noticed that one of your commands pipes ls -l into awk. See Why not parse ls (and what to do instead)? for why that's a terrible idea. Use stat instead, it can give you a file's timestamp (or other metadata) without any need to parse ls - e.g. with GNU stat: stat --printf='%y' /var/lib/apt/periodic/update-success-stamp (or use %Y instead of %y to get the seconds since epoch instead of a human-readable data, and use that with date to format it however you want).
    – cas
    Nov 11, 2022 at 1:55

2 Answers 2

1
  1. bash history generally doesn't record the timestamp of a command (and in my experience, setting the HISTTIMEFORMAT variable doesn't do anything useful).

  2. You can check the timestamp of /var/log/dpkg.log (which is a quick way to find out the last time a package was installed/upgraded/removed) or examine the contents of /var/log/apt/history.log (which you can parse to get more details on exactly what actions were performed, and when).

e.g. the last two records from /var/log/apt/history.log on one of my systems are:

Start-Date: 2022-11-09  19:51:36
Commandline: apt -m -u dist-upgrade
Install: libjxl0.7:amd64 (0.7.0-5+b1, automatic), libhwy1:amd64 (1.0.2-4, automatic), libicu72:amd64 (72.1-2, automatic)
Upgrade: libvulkan1:amd64 (1.3.224.0-1, 1.3.231.1-1), libvulkan1:i386 (1.3.224.0-1, 1.3.231.1-1), libglib2.0-dev-bin:amd64 (2.74.1-1, 2.74.1-2), udev:amd64 (252-3, 252.1-1), source-highlight:amd64 (3.1.9-4.2, 3.1.9-4.2+b1), libglx-mesa0:amd64 (22.2.2-1, 22.2.3-1), libglx-mesa0:i386 (22.2.2-1, 22.2.3-1), systemd-container:amd64 (252-3, 252.1-1), libpciaccess-dev:amd64 (0.17-1, 0.17-2), libglib2.0-bin:amd64 (2.74.1-1, 2.74.1-2), vulkan-tools:amd64 (1.3.224.0+dfsg1-1, 1.3.231.1+dfsg1-1), libglib2.0-dev:amd64 (2.74.1-1, 2.74.1-2), libglib2.0-doc:amd64 (2.74.1-1, 2.74.1-2), pristine-tar:amd64 (1.49, 1.50), ffmpeg-doc:amd64 (10:5.1.2-dmo1, 10:5.1.2-dmo2), libpam-systemd:amd64 (252-3, 252.1-1), libboost-iostreams1.74.0:amd64 (1.74.0-17, 1.74.0-17+b1), libgbm1:amd64 (22.2.2-1, 22.2.3-1), libgbm1:i386 (22.2.2-1, 22.2.3-1), libpciaccess0:amd64 (0.17-1, 0.17-2), libpciaccess0:i386 (0.17-1, 0.17-2), systemsettings:amd64 (4:5.26.2-1, 4:5.26.3-1), kwrited:amd64 (4:5.26.2-1, 4:5.26.3-1), liboxygenstyleconfig5-5:amd64 (4:5.26.2-1, 4:5.26.3-1), libdrm-nouveau2:amd64 (2.4.113-2, 2.4.114-1), libdrm-nouveau2:i386 (2.4.113-2, 2.4.114-1), libsystemd0:amd64 (252-3, 252.1-1), libsystemd0:i386 (252-3, 252.1-1), libavdevice59:amd64 (10:5.1.2-dmo1, 10:5.1.2-dmo2), plasma-discover-common:amd64 (5.26.2-1, 5.26.3-1), ffmpeg:amd64 (10:5.1.2-dmo1, 10:5.1.2-dmo2), systemd-journal-remote:amd64 (252-3, 252.1-1), kde-style-oxygen-qt5:amd64 (4:5.26.2-1, 4:5.26.3-1), libudev-dev:amd64 (252-3, 252.1-1), libboost-filesystem1.74.0:amd64 (1.74.0-17, 1.74.0-17+b1), libboost-thread1.74.0:amd64 (1.74.0-17, 1.74.0-17+b1), libglib2.0-data:amd64 (2.74.1-1, 2.74.1-2), kactivitymanagerd:amd64 (5.26.2-1, 5.26.3-1), systemd:amd64 (252-3, 252.1-1), libudev1:amd64 (252-3, 252.1-1), libudev1:i386 (252-3, 252.1-1), libpostproc56:amd64 (10:5.1.2-dmo1, 10:5.1.2-dmo2), libgl1-mesa-dev:amd64 (22.2.2-1, 22.2.3-1), libgl1-mesa-dri:amd64 (22.2.2-1, 22.2.3-1), libgl1-mesa-dri:i386 (22.2.2-1, 22.2.3-1), libosmesa6:amd64 (22.2.2-1, 22.2.3-1), libosmesa6:i386 (22.2.2-1, 22.2.3-1), libdrm-common:amd64 (2.4.113-2, 2.4.114-1), libboost-locale1.74.0:amd64 (1.74.0-17, 1.74.0-17+b1), libswscale-dev:amd64 (10:5.1.2-dmo1, 10:5.1.2-dmo2), libboost-python1.74.0:amd64 (1.74.0-17, 1.74.0-17+b1), ksshaskpass:amd64 (4:5.26.2-1, 4:5.26.3-1), libavcodec59:amd64 (10:5.1.2-dmo1, 10:5.1.2-dmo2), libavutil57:amd64 (10:5.1.2-dmo1, 10:5.1.2-dmo2), liboxygenstyle5-5:amd64 (4:5.26.2-1, 4:5.26.3-1), libswscale6:amd64 (10:5.1.2-dmo1, 10:5.1.2-dmo2), libavogadro2-1:amd64 (1.97.0-2, 1.97.0-3), dh-elpa-helper:amd64 (2.0.14, 2.0.15), kmenuedit:amd64 (4:5.26.2-1, 4:5.26.3-1), libicu-dev:amd64 (71.1-3, 72.1-2), libavutil-dev:amd64 (10:5.1.2-dmo1, 10:5.1.2-dmo2), libglapi-mesa:amd64 (22.2.2-1, 22.2.3-1), libglapi-mesa:i386 (22.2.2-1, 22.2.3-1), libboost-wave1.74.0:amd64 (1.74.0-17, 1.74.0-17+b1), libglib2.0-0:amd64 (2.74.1-1, 2.74.1-2), libglib2.0-0:i386 (2.74.1-1, 2.74.1-2), libboost-program-options1.74.0:amd64 (1.74.0-17, 1.74.0-17+b1), btrfs-progs:amd64 (6.0-1, 6.0.1-1), libdrm-amdgpu1:amd64 (2.4.113-2, 2.4.114-1), libdrm-amdgpu1:i386 (2.4.113-2, 2.4.114-1), libdrm-radeon1:amd64 (2.4.113-2, 2.4.114-1), libdrm-radeon1:i386 (2.4.113-2, 2.4.114-1), libdrm2:amd64 (2.4.113-2, 2.4.114-1), libdrm2:i386 (2.4.113-2, 2.4.114-1), libsystemd-shared:amd64 (252-3, 252.1-1), libswresample4:amd64 (10:5.1.2-dmo1, 10:5.1.2-dmo2), libboost-regex1.74.0:amd64 (1.74.0-17, 1.74.0-17+b1), mupdf:amd64 (1.20.3+ds1-1+b1, 1.21.0+ds1-1), systemd-sysv:amd64 (252-3, 252.1-1), libavformat59:amd64 (10:5.1.2-dmo1, 10:5.1.2-dmo2), libegl-mesa0:amd64 (22.2.2-1, 22.2.3-1), libegl-mesa0:i386 (22.2.2-1, 22.2.3-1), mupdf-tools:amd64 (1.20.3+ds1-1+b1, 1.21.0+ds1-1), dwarves:amd64 (1.24-2, 1.24-3), mesa-vdpau-drivers:amd64 (22.2.2-1, 22.2.3-1), libavcodec-dev:amd64 (10:5.1.2-dmo1, 10:5.1.2-dmo2), bluedevil:amd64 (4:5.26.2-1, 4:5.26.3.1-1), pahole:amd64 (1.24-2, 1.24-3), libdrm-intel1:amd64 (2.4.113-2, 2.4.114-1), libdrm-intel1:i386 (2.4.113-2, 2.4.114-1), libkworkspace5-5:amd64 (4:5.26.2-1, 4:5.26.3-1), libsource-highlight4v5:amd64 (3.1.9-4.2, 3.1.9-4.2+b1), icu-devtools:amd64 (71.1-3, 72.1-2), libswresample-dev:amd64 (10:5.1.2-dmo1, 10:5.1.2-dmo2), libavfilter8:amd64 (10:5.1.2-dmo1, 10:5.1.2-dmo2)
Remove: libflightcrew0v5:amd64 (0.9.3+dfsg-1+b4), libaqsis1:amd64 (1.8.2+git20210815-1+b1), flightcrew:amd64 (0.9.3+dfsg-1+b4), aqsis:amd64 (1.8.2+git20210815-1+b1)
End-Date: 2022-11-09  19:54:06

Start-Date: 2022-11-09  19:59:28
Commandline: apt-get -u install linux-image-amd64 linux-headers-amd64
Install: linux-image-6.0.0-3-amd64:amd64 (6.0.7-1, automatic), linux-headers-6.0.0-3-amd64:amd64 (6.0.7-1, automatic), linux-headers-6.0.0-3-common:amd64 (6.0.7-1, automatic)
Upgrade: linux-headers-amd64:amd64 (6.0.6-2, 6.0.7-1), linux-image-amd64:amd64 (6.0.6-2, 6.0.7-1)
End-Date: 2022-11-09  20:07:29

These records are conveniently in "paragraph"-format (i.e. separated by a blank line) so can easily be processed with awk -v RS="" or perl -00.


NOTE: the apt history log only records things done by apt and friends. It doesn't record anything done by dpkg alone. The dpkg.log file, however, records anything done by dpkg itself AND anything done by apt/apt-get/aptitude or any other tool that ends up executing dpkg to install/upgrade/remove a package.

In other words, dpkg -i /path/to/package.deb or dpkg --purge packagename will be recorded in /var/log/dpkg.log, but not in /var/log/apt/history.log (because it doesn't use apt at all). apt-get install package or apt purge package will be recorded in both (because apt and apt-get both use dpkg to perform the install/remove/etc operation).

0

I do not have paramiko, so I'll give an adjacent answer using subprocess: subprocess.call("bash -i -c 'history -r; history'", shell=True). Or just scrape the bash history file by catting ~/.bash_history or ~/.history. history is a shell built-in and runs interactively unlike other executables found within the PATH and displays command execution history not timestamps. Rhetorical comment: this seems like something you can run with a shell script.

Some other links to research:

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .