There was a situation when somebody moved the whole rootdir into a subdir on a remote system, thus all the system tools like cp, mv, etc didn't work anymore. We had an active session though but couldn't find a way to copy/move the files back using only bash built-ins.
Do somebody know of a way to achieve this?
I even thought about copy the cp or mv binary in the currentdir with
while read -r; do echo $LINE; done
and then redirect this to a file, but it didn't work. Guess because of all the special non printable chars in a binary file that can't be copied/displayed using echo.
thanks.
/newroot/lib/ld-linux.so.2 --library-path /newroot/lib \
/newroot/bin/mv /newroot/* /
(Similar for Solaris, but I think the dynamic linker is named ld.so.1 or something along those lines.)
Or, if your shell is sh-like (not csh-like),
LD_LIBRARY_PATH=/newroot/lib /newroot/bin/mv /newroot/* /
If you have prepared with sash pre-installed, then that is static and has a copy built-in (-cp).
Otherwise LD_LIBRARY_PATH=/copied/to/path/lib /copied/to/path/bin/cp might work?
I think it might have a problem with not having ld-so in the expected place.
Here's a reasonable ghetto replacement for cp. You'll want echo -E if the file ends with a new line (like most text files), echo -nE if it doesn't (like most binaries).
echo -nE "`< in.file`" > out.file
Old thread, but got exactly the same stupid mistake. /lib64 was moved to /lib64.bak remotely and everything stopped working.
This was a x86_64 install, so ephemient's solution was not working:
# /lib64.bak/ld-linux.so.2 --library-path /lib64.bak/ /bin/mv /lib64.bak/ /lib64
/bin/mv: error while loading shared libraries: /bin/mv: wrong ELF class: ELFCLASS64
In that case, a different ld-linux had to be used:
# /lib64.bak/ld-linux-x86-64.so.2 --library-path /lib64.bak/ /bin/mv /lib64.bak/ /lib64
Now the system is salvaged. Thanks ephemient!
/subdir/bin/mv /subdir /
or am I missing something in your explanation?
If you have access to another machine, one solution is to download and compile a Busybox binary. It will be a single binary contains most of the common tools you need to restore your system. This might not work if your system is remote though.
Related
I'm not even sure if this is easily possible, but I would like to list the files that were recently deleted from a directory, recursively if possible.
I'm looking for a solution that does not require the creation of a temporary file containing a snapshot of the original directory structure against which to compare, because write access might not always be available. Edit: If it's possible to achieve the same result by storing the snapshot in a shell variable instead of a file, that would solve my problem.
Something like:
find /some/directory -type f -mmin -10 -deletedFilesOnly
Edit: OS: I'm using Ubuntu 14.04 LTS, but the command(s) would most likely be running in a variety of Linux boxes or Docker containers, most or all of which should be using ext4, and to which I would most likely not have access to make modifications.
You can use the debugfs utility,
debugfs is a simple to use RAM-based file system specially designed
for debugging purposes
First, run debugfs /dev/hda13 in your terminal (replacing /dev/hda13 with your own disk/partition).
(NOTE: You can find the name of your disk by running df / in the terminal).
Once in debug mode, you can use the command lsdel to list inodes corresponding with deleted files.
When files are removed in linux they are only un-linked but their
inodes (addresses in the disk where the file is actually present) are
not removed
To get paths of these deleted files you can use debugfs -R "ncheck 320236" replacing the number with your particular inode.
Inode Pathname
320236 /path/to/file
From here you can also inspect the contents of deleted files with cat. (NOTE: You can also recover from here if necessary).
Great post about this here.
So a few things:
You may have zero success if your partition is ext2; it works best with ext4
df /
Fill mount point with result from #2, in my case:
sudo debugfs /dev/mapper/q4os--desktop--vg-root
lsdel
q (to exit out of debugfs)
sudo debugfs -R 'ncheck 528754' /dev/sda2 2>/dev/null (replace number with one from step #4)
Thanks for your comments & answers guys. debugfs seems like an interesting solution to the initial requirements, but it is a bit overkill for the simple & light solution I was looking for; if I'm understanding correctly, the kernel must be built with debugfs support and the target directory must be in a debugfs mount. Unfortunately, that won't really work for my use-case; I must be able to provide a solution for existing, "basic" kernels and directories.
As this seems virtually impossible to accomplish, I've been able to negotiate and relax the requirements down to listing the amount of files that were recently deleted from a directory, recursively if possible.
This is the solution I ended up implementing:
A simple find command piped into wc to count the original number of files in the target directory (recursively). The result can then easily be stored in a shell or script variable, without requiring write access to the file system.
DEL_SCAN_ORIG_AMOUNT=$(find /some/directory -type f | wc -l)
We can then run the same command again later to get the updated number of files.
DEL_SCAN_NEW_AMOUNT=$(find /some/directory -type f | wc -l)
Then we can store the difference between the two in another variable and update the original amount.
DEL_SCAN_DEL_AMOUNT=$(($DEL_SCAN_ORIG_AMOUNT - $DEL_SCAN_NEW_AMOUNT));
DEL_SCAN_ORIG_AMOUNT=$DEL_SCAN_NEW_AMOUNT
We can then print a simple message if the number of files went down.
if [ $DEL_SCAN_DEL_AMOUNT -gt 0 ]; then echo "$DEL_SCAN_DEL_AMOUNT deleted files"; fi;
Return to step 2.
Unfortunately, this solution won't report anything if the same amount of files have been created and deleted during an interval, but that's not a huge issue for my use case.
To circumvent this, I'd have to store the actual list of files instead of the amount, but I haven't been able to make that work using shell variables. If anyone could figure that out, I'd help me immensely as it would meet the initial requirements!
I'd also like to know if anyone has comments on either of the two approaches.
Try:
lsof -nP | grep -i deleted
history >> history.txt
Look for all rm statements.
I'm running through the "first kernel patch" tutorial on kernel newbies http://kernelnewbies.org/FirstKernelPatch
While running through the tutorial, i've had absolutely no issues what so ever until now, I am at a point where I am setting up my kernel configuration. I've followed the tutorial exactly as shown but the following command:
cp /boot/config-'uname -r'* .config
leaves me with the following error message in the terminal:
cp: cannot stat '/boot/config-uname -r*': No such file or directory
Is there a way I can generate this file without going through the effort of looking for it in the finder? I'd rather not go through the thousands of files there are in a kernel, it could take me forever.
It seems like your tutorial has a quotation error. instead of ' you should be using ` (backtick)
cp /boot/config-`uname -r`* .config
What it does is execute the command uname -r and place the stdout of the command in place of the command. I'd suggest using $(command) instead of `command` since it's more obvious what is going on.
cp /boot/config-$(uname -r)* .config
First things first .. You're using simple quotes which is wrong, the command is meant to use backticks (`) -- they will include the output of the command inside them:
> uname -r
3.16.1-ck1
> echo /boot/config-`uname -r`
/boot/config-3.16.1-ck1
So this could already solve your problem.
If this file isn't present on your system, you have some alternatives:
If you have the source the running kernel is built from, the kernel config is the file .config there.
Although most packaging/installation systems copy the kernel config to /boot/config-`uname -r`, some just copy it to /boot/config (without version suffix)
The kernel can be built to serve it's config in /proc/config.gz (gzip compressed)
If really neither of these succeed, you're out of luck and your only option is get hold of the source package your kernel is built from.
I want to move /bin/ls to /root, but I typed a wrong dir:
mv /bin/ls /roo
Now I couldn't find the ls command file, how can I retrieve it?
First of all, why do you want to do that?? Careful with root privilege!!
Unless you have an extremely good reason and know exactly what you're doing, don't move unix commands from /bin. For one thing, other OS components and libraries may depend on them and you could totally hose your system.
ls is used from various binaries in subprocesses to list files.
Do this to recover, if you're sure what you're showing here is what you did to move it exactly.
mv /roo /bin/ls
I want to rsync a directory to server from a mac machine to linux machine while excluding compiled files like .o files and binary executables. How do I exclude binary files?
What I am using at the moment:
rsync -av --compress --exclude="*.o" dir server:dir
This is a sticky problem because a Unix system does not have a hard and fast definition of the distinction between "binary" and "text" files. You can do a pretty good job by using the file command and searching for text in the output (see How to tell binary from text files in linux), so I'd run find to generate a list of files which file considers to be text, and use that as the list of files to rsync:
find dir | xargs file | awk -F: '$2 ~ /text/ { print $1 }' | \
rsync --files-from=- -av --compress dir server:dir
This will require some tweaking to make sure the pathnames are correct relative to the source dir, and so on, but it should get close to what you want.
In the long term, I'd want to rework my build process to put generated files in a dir/build directory, but this might help for now :-)
You can add a .cvsignore file in the directories and use the option -C to rsync.
But this is only vaguely what you specified. Maybe it suits you well, maybe it assumes other things than you. So be careful and test that properly.
Also, you can run a find before the rsync, scanning the complete tree for files matching your idea of being "binary" (maybe compiled executables?), and place all their names in an exclude file which you then use with option --exclude-from.
I'd like to do ls without seeing all the ~ files generated by vim. Is it possible?
This is better solved from within vim, as opposed to bash.
Use
set backupdir=~/.backup,/tmp
to put all your ~ files in the ~/.backup directory. Change that directory to whatever you want. The /tmp means that it will act as a fallback to the ~/.backup directory.
If you don't want backup files to be generated at all, you can use
set nobackup
set nowritebackup
to disable it, but you will of course lose that functionality.
EDIT:
Although the above solution is still the one I recommend because you can do more with it, I just realized that ls has a -B option which will hide files ending with ~. I've aliased it myself, and never noticed. If you really want, you can alias ls -B and go with that.
EDIT v2.0:
As noted by Wesley, some platforms' ls command have different meanings for -B, some may not have it at all. I'm using the GNU ls, and it has had this switch for as long as I can remember.
Many editors use the ~ files to represent backup files. (I use this trick to hide the backup files from gedit.) To disable them from showing, add this command to your bashrc:
alias ls='ls --hide=*~'
Edit: Mac OS X ls does not appear to have this option, so it follows that BSD ls probably doesn't have it either. Ubuntu does have this option, so many Linux distributions probably do; check your manual pages. In addition, Mac ls appears to have a different -B, so consider this when using Sykora's advice.
You'll be sorrrrryyyy if you just hide them from ls. They'll still be there as far as grep and other tools are concerned except that now you can't see them. Moving them to /tmp is a much better way to go.
This problem is ESPECIALLY severe with .svn directories, which have all kinds of useless cr*p that you really don't want to edit. I don't know a solution to that one.
For Mac OS X:
brew install coreutils
echo "alias ls='/usr/local/bin/gls -B'" >> ~/.bashrc