1

Is there any ways to find out what file content has been modified or added in Linux. I am aware of the atime,ctime,mtime. Say I created a script "myscript.sh" and somebody changed some content of it e.g. added few lines of code or deleted. I want know what content has been changed since the file was created?

Any thoughts?

  • 5
    You're after a code versioning system, i.e. git, mercurial, svn, cvs. The purpose of a CVS is exactly that: ensure that you know what changes have been made, when, and by whom. – grochmal Jul 6 '16 at 22:06
  • I second @grochmal. Just learn a VCS (version control system). RCS is fairly widespread (may already be installed) but ancient and kind of clunky. Git is extremely available, fast, efficient, and powerful. – Wildcard Jul 6 '16 at 22:16
  • 1
    I used VCS in my answer (see below) – InitializeSahib Jul 6 '16 at 22:17
  • As @grochmal says, however it is called a “revision control system”. Many many people mix up version control, revision control, and configuration control, they are all different and closely related. – ctrl-alt-delor Jul 6 '16 at 22:18
  • Upvoting. I don't see any fundamental problem in the question body. – InitializeSahib Jul 6 '16 at 22:54
0

Based on your comments to @SahibPrime's answer, you should use etckeeper

From the home page:

etckeeper is a collection of tools to let /etc be stored in a git, mercurial, bazaar or darcs repository. This lets you use git to review or revert changes that were made to /etc. Or even push the repository elsewhere for backups or cherry-picking configuration changes.

It hooks into package managers like apt to automatically commit changes made to /etc during package upgrades. It tracks file metadata that git does not normally support, but that is important for /etc, such as the permissions of /etc/shadow.

It's quite modular and configurable, while also being simple to use if you understand the basics of working with version control.

One thing SahibPrime didn't mention was that you can use git diff to view changes that were made between current and/or any previous committed versions, and when those changes were made. You can also easily revert to any previous version of any revision-controlled file.

On Debian, at least, it runs daily from cron, so you don't even need to remember to commit changes. It almost certainly runs from cron on other distros too.

Install it and completely forget about it until you need it. Requires no maintenance.

You can also use git (or any other similar software) to track changes in /usr/local. I used to use RCS for years in /etc and in directories like /usr/local/{s,}bin/ and ~/bin. Later I switched to svn. etckeeper and git are better.


tldr: gitmeoutofhere

I must have switched to etckeeper back in 2012. I have revision history of every change (at least daily and before/after every apt install or upgrade) since then.

# git log | tail -5 
commit 7e3bb0eade7ae9e211bb684be2e3c7d4a3128c24
Author: ...my.email.address.deleted...
Date:   Wed Feb 29 12:53:30 2012 +1100

    Initial commit

# git log | grep '^commit' | wc -l
1378

I almost never have to look at it or think about it or even remember that it's there, but when i need it, it's invaluable. I can undo any stupid thing i might do and instantly get back a known working and good version of any config file.

Here's some of the things I can do with all that revision history of my config files:

I can see a list of commits for specific files:

# git log apache2/apache2.conf | sed -ne 's/commit //p'  | head
2d0fabf90f2bc639d30bca925147fafd3fbd5e50
8022c7ca6dbe1661064604a646c52ca0d1f1b3ac
0620c88b8d1fd625f74f42059a4e8f056846df16
8c2fcfef72eca034b251654be44a268e92e39416
02329cf86655a2bb2c09c793b1d195a4de579cf1
5e449105f0ab75f9e903d8c75af5c8db6543c281
d8339212967af2c664b0c1776e9352f6c0e12ff8
7e3bb0eade7ae9e211bb684be2e3c7d4a3128c24

I can see when any of those commits happened:

# git log 8022c7ca6dbe1661064604a646c52ca0d1f1b3ac | head -5
commit 8022c7ca6dbe1661064604a646c52ca0d1f1b3ac
Author: ...
Date:   Tue Aug 20 12:26:53 2013 +1000

    committing changes in /etc after apt run

and i can see the diff:

# git diff 8022c7ca6dbe1661064604a646c52ca0d1f1b3ac apache2/apache2.conf
diff --git a/apache2/apache2.conf b/apache2/apache2.conf
index baf6d8a..617152c 100644
--- a/apache2/apache2.conf
+++ b/apache2/apache2.conf
@@ -71,7 +71,7 @@
 #
 # The accept serialization lock file MUST BE STORED ON A LOCAL DISK.
 #
-Mutex file:${APACHE_LOCK_DIR} default
+#Mutex file:${APACHE_LOCK_DIR} default

 #
 # PidFile: The file in which the server should record its process

And I can revert anything and/or everything to any previous version. Most useful is reversion of an individual file:

# git checkout 8022c7ca6dbe1661064604a646c52ca0d1f1b3ac apache2/apache2.conf
# git diff 8022c7ca6dbe1661064604a646c52ca0d1f1b3ac apache2/apache2.conf
#

I can see a list of files that have changed since the last commit:

# git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   apache2/apache2.conf

no changes added to commit (use "git add" and/or "git commit -a")

If I wanted to, I could commit that again (with git add and git commit) or change my mind and bring back the latest commit:

# git checkout 2d0fabf90f2bc639d30bca925147fafd3fbd5e50 apache2/apache2.conf
# git help status
# 
3

You can do this in a VCS way via git.
First, install git (it should be pre-installed, if not, your package manager should have it)
For Debian systems: sudo apt-get install git
Then, make a directory to keep your file in (mkdir myDir)
Go into the directory, and run git init. (This will create a local Git repository).
Add your file to the directory, then run git add -f *.
Now, you can run git commit -m "file before editing" to save your file as it is.
You can run git status to see if the file has been edited or not. It'll show something like:

modified: myFile.txt

If you want to rollback the file to the last time you ran git commit, you can run git reset --hard HEAD^. This will force the local repository to go back to the last commit.

You can save a new change to the file with git commit, like so:

git commit -m "added 4 lines"

If you want to see a list of commits (and their messages), you can run git log.


VCS was designed for this, which I why I used it in my answer.

  • Is there any built in Linux command line tools which I can use? – Bustam Jul 6 '16 at 22:12
  • 1
    @HusnainBustam, define "built in." For which distro? Which version? I don't believe there is any version control tool specified by POSIX, but Git is cross platform, easy to install, extremely flexible and should be part of every power user's toolkit. Just learn it. – Wildcard Jul 6 '16 at 22:18
  • 1
    I am aware of Subversion control tools. Today the problem arise something like this, somebody made a change in one of the configuration files in Linux servers. From the "stat" command I can see the atime, mtime,ctime etc. But I was curious to know what content has been changes, it there any ways in Linux except using the SVC tools? – Bustam Jul 6 '16 at 22:18
  • 1
    @richard Hard? I mean sure if you want to learn how to use git for managing remote repositories and projects, but for this scenario, everything needed to know I have listed in my answer. – InitializeSahib Jul 6 '16 at 22:23
  • 1
    @HusnainBustam Husnain, if you are looking for a certain type of answer, you can edit your question to clarify. – InitializeSahib Jul 6 '16 at 22:25
1

There's ordinarily no facility built into Unix (or rather, built into the most common file systems of Unix like it is/was on OpenVMS), so you can't expect to retrieve earlier versions of a file.

The simplest solution would be to keep a personal copy of the files you'd like to "monitor", and then periodically run diff over these and the copies installed on the system.

The next step up is to keep the files in some sort of revision control system. The most readily available of these on Unix is usually RCS which is very basic but that does what it says on the tin.

Git is more sophisticated, but may be too much hassle if this concerns just one or a handful of files (RCS handles individual files and has no concept of "a repository" of many files that belong together).

0

Wouldn't a "diff" suffice? diff oldfile newfile > changes would put all of the differences into the file name changes with the appropriate line numbers.

Alan

  • Say I don't have the backup of the old file. In that case is there any way? – Bustam Jul 6 '16 at 22:09
  • 1
    @HusnainBustam, If you don't have a backup, how on earth do you expect to compare your file to the previous version? Computers are tools, they are not magic wands. – Wildcard Jul 6 '16 at 22:14
  • 1
    @Wildcard: Well, Microsoft Office (Word, Excel, etc.) lets you magically undo most changes and even recover previous versions of files.  If the OP is familiar with Office and new to Linux, this question is not totally unreasonable. – G-Man Jul 6 '16 at 22:38
  • 1
    @HusnainBustam Some editors leave a file with a ~ after its name. This is a backup file. If you find it, move it to the changed file's location. If you don't, try looking for backups in other places or a skeleton in /etc/skel. – InitializeSahib Jul 6 '16 at 22:46
  • @G-Man, a fair point, but that's related to the editor used, not the file itself. Good you brought that up, though. – Wildcard Jul 6 '16 at 22:50
0

You may be looking for an intrusion detection system (an IDS). Some IDSs will periodically examine all the files on your system, and alert you to unexpected changes. The classic example is tripwire, but I've been getting a 403 on tripwire.org for the last eight hours.

Such systems usually just remember the checksums of the files, so to know what has has changed, you need to compare to your backups.

  • tripwire.org is displaying perfectly for me – InitializeSahib Jul 6 '16 at 22:45
  • @SahibPrime If tripware is tracking the file and didn't flag a change it is unlikely the file was changed. – BillThor Jul 6 '16 at 23:49
0

A last resort method, for those that did not use revision control. Warning: Check the prerequisites, it may not work in your situation. I have only done this twice.

Prerequisites:

  • The file was changed by an editor that replaced the file: unlink, create; or create, unlink, move. (not by modifying original)
  • The original file is still open by at least one process on the system.
  • You are smart, patient, and have the time.
  • You are lucky (remember “the more I practice the luckier I get”).

Method:

  1. Find the process that still has the original file open. (Hint: lsof)
  2. Identify the PID of this process.
  3. Navigate into /proc/«pid»/fd.
  4. Identify the file-descriptor (a number: 0 is stdin, 1 stdout, 2 stderr, other numbers for other files) for the file that you are looking for.
  5. Copy the file from /proc/«pid»/fd/«file-descriptor» to a persistent storage area (hard-disk).

Warning: this is magic (thanks to @wildcard for reminding me of this).

  • 1
    i don't think the original file is still open by now – InitializeSahib Jul 6 '16 at 22:45
  • This answer is internally correct, but extremely misleading since it's extremely unlikely to be applicable in the context of the question. – Gilles Jul 6 '16 at 23:47
  • @giles I agree that it is unlikely, but it is as far as I can tell the only one that does not involve a time-machine. The other solutions are good, but are of the form “this is how you avoid this problem next time”. I love these solutions as they are the best in the long term. However we also need a short term solution. As is the nature of these short term (panic) solutions, we need a few, and we need to try them, and hope to be lucky. – ctrl-alt-delor Jul 7 '16 at 8:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.