What is dot in ls -l command on Linux? - linux

I ran ls -l on my centOS 6.10 on a specific file.
My question is what is the meaning of this dot(.) before 1?
-rw-r--r--. 1 root root 575 Oct 23

It means that the file has an SELinux context. Use ls -Z to see the actual SElinux context values. It's documented on the "info" file for GNU Coreutils: What-information-is-listed.
The relevant quote:
Following the file mode bits is a single character that specifies
whether an alternate access method such as an access control list
applies to the file. When the character following the file mode
bits is a space, there is no alternate access method. When it is a
printing character, then there is such a method.
GNU ‘ls’ uses a ‘.’ character to indicate a file with a security
context, but no other alternate access method.
A file with any other combination of alternate access methods is
marked with a ‘+’ character.
Follow the link for more details

Related

Is it possible to display a file's contents and delete that file in the same command?

I'm trying to display the output of an AWS lambda that is being captured in a temporary text file, and I want to remove that file as I display its contents. Right now I'm doing:
... && cat output.json && rm output.json
Is there a clever way to combine those last two commands into one command? My goal is to make the full combined command string as short as possible.
For cases where
it is possible to control the name of the temporary text file.
If file is not used by other code
Possible to pass "/dev/stdout" as the.name of the output
Regarding portability: see stack exchange how portable ... /dev/stdout
POSIX 7 says they are extensions.
Base Definitions,
Section 2.1.1 Requirements:
The system may provide non-standard extensions. These are features not required by POSIX.1-2008 and may include, but are not limited to:
[...]
• Additional character special files with special properties (for example,  /dev/stdin, /dev/stdout,  and  /dev/stderr)
Using the mandatory supported /dev/tty will force output into “current” terminal, making it impossible to pipe the output of the whole command into different program (or log file), or to use the program when there is no connected terminals (cron job, or other automation tools)
No, you cannot easily remove the lines of a file while displaying them. It would be highly inefficient as it would require removing characters from the beginning of a file each time you read a line. Current filesystems are pretty good at truncating lines at the end of a file, but not at the beginning.
A simple but extremely slow method would look like this:
while [ -s output.json ]
do
head -1 output.json
sed -i 1d output.json
done
While this algorithm is plain and simple, you should know that each time you remove the first line with sed -i 1d it will copy the whole content of the file but the first line into a temporary file, resulting in approximately 0.5*n² lines written in total (where n is the number of lines in your file).
In theory you could avoid this by do something like that:
while [ -s output.json ]
do
line=$(head -1 output.json)
printf -- '%s\n' "$line"
fallocate -c -o 0 -l $((${#len}+1)) output.json
done
But this does not account for variable newline characters (namely DOS-formatted newlines) and fallocate does not always work on xfs, among other issues.
Since you are trying to consume a file alongside its creation without leaving a trace of its existence on disk, you are essentially asking for a pipe functionality. In my opinion you should look into how your output.json file is produced and hopefully you can pipe it to a script of your own.

Applying a patch to files with spaces in names

Here's an output of diff -u "temp temp/docs 1.txt" "temp temp/docs 2.txt":
--- temp temp/docs 1.txt Mon Apr 7 16:15:08 2014
+++ temp temp/docs 2.txt Mon Apr 7 16:18:45 2014
## -2,6 +2,6 ##
22
333
4444
-555555
+55555
666666
7777777
However, feeding this diff to patch -u fails with following message:
can't find file to patch at input line 3
Perhaps you should have used the -p or --strip option?
The text leading up to this was:
--------------------------
|--- temp temp/docs 1.txt Mon Apr 7 16:15:08 2014
|+++ temp temp/docs 2.txt Mon Apr 7 16:18:45 2014
--------------------------
Apparently, the spaces are the problem; is there a way to make patch to work on files with spaces in names?
No, GNU patch doesn't support this. Here's the official statement: http://www.gnu.org/software/diffutils/manual/html_node/Unusual-File-Names.html#Unusual%20File%20Names
Gnu patch 2.6.1 (linux) seems to obey at least 1 space (not tried with more) if the filename is separated from the date with tab.
YYMV
I encountered the same problem when trying to establish conventions how to do manual version control with diff and patch.
I found out that GNU "diff" creates quoted path names in the patch headers if they contain spaces, while BusyBox "diff" doesn't.
Neither GNU nor BusyBox "patch" accepts quoted path names.
If the problem is just embedded spaces within filenames, it can therefore be avoided by using "busybox patch" rather than GNU "patch".
Another solution is to postprocess the output of GNU "diff" before feeding it into "patch":
sed 's,^\([-+]\{3\} \)"\([^"]*\)",\1\2,' $PATCHFILE | patch -p1
This works whether $PATCHFILE was created with GNU or busybox diff, but will only work with unified diff format.
Unfortunately, it turns out that leading or trailing spaces in filenames cannot be preserved with this method, as "patch" will skip them when parsing the path names from the patch instructions.
The approach will neither work if the filename starts with a literal double quote - but then, who uses such file names?
Most of the time, however, the above approach works just fine.
Finally a note of other approaches I have also tried but which did not work:
First I tried to replace the quotation of the whole path names by individually quoted path name components. This failed because "patch" does not use double quotes as meta-characters at all. It considers them to be normal literal characters.
Then I tried to replace all spaces by "\040" like CVS does - but "patch" does not seem to accept octal-escapes either, and this failed too.

Using -s command in bash script

I have a trivial error that I cant seem to get around. Im trying to return the various section numbers of lets say "man" since it resides in all the sections. I am using the -s command but am having problems. Every time I use it I keep getting "what manual page do you want". Any help?
In the case of getting the section number of a command, you want something like man -k "page_name" | awk -F'-' "/^page_name \(/ {print $1}", replacing any occurrence of page_name with whatever command you're needing.
This won't work for all systems necessarily as the format for the "man" output is "implementation-defined". In other words, the format on FreeBSD, OS X, various flavours of Linux, etc. may not be the same. For example, mine is:
page_name (1) - description
If you want the section number only, I'm sure there is something you can do such as saving the result of that line in a shell variable and use parameter expansion to remove the parentheses around the section number:
man -k "page_name" | awk -F'-' "/^page_name \(/ {print $1}" | while IFS= read sect ; do
sect="${sect##*[(]}"
sect="${sect%[)]*}"
printf '%s\n' "$sect"
done
To get the number of sections a command appears in, add | wc -l at the end on the same line as the done keyword. For the mount command, I have 3:
2
2freebsd
8
You've misinterpreted the nature of -s. From man man:
-S list, -s list, --sections=list
List is a colon- or comma-separated list of `order specific' manual sections to search. This option overrides the
$MANSECT environment variable. (The -s
spelling is for compatibility with System V.)
So when man sees man -s man it thinks you want to look for a page in section "man" (which most likely doesn't exist, since it is not a normal section), but you didn't say what page, so it asks:
What manual page do you want?
BTW, wrt "man is just the test case cuz i believe its in all the sections" -- nope, it is probably only in one, and AFAIK there isn't any word with a page in all sections. More than 2 or 3 would be very unusual.
The various standard sections are described in man man too.
The correct syntax requires an argument. Typically you're looking for either
man -s 1 man
to read the documentation for the man(1) command, or
man -s 7 man
to read about the man(7) macro package.
If you want a list of standard sections, the former contains that. You may have additional sections installed locally, though. A directory listing of /usr/local/share/man might reveal additional sections, for example.
(Incidentally, -s is not a "command" in this context, it's an option.)

The "->" Notation in linux

What does the "->" notation mean in Linux .
eg. When I do ls -l in a particular folder, I get the following.
lrwxrwxrwx 1 root root 29 Feb 27 12:23 ojdbc.jar -> /apps/hadoop/sqoop/ojdbc6.jar
Is the first file a placeholder of the second one?
Kind Regards.
It means the file is not a physical file, but a symbolic link pointing to the file to the right of the arrow.
The command "ls -l" uses "->" to denote a symbolic-link (that is, a psuedo-file which only points to another file).
In your example ojdbc.jar is a symbolic-link to /apps/hadoop/sqoop/ojdbc6.jar.
I'm not aware that this meaning holds beyond ls, however.

How do I increase the /proc/pid/cmdline 4096 byte limit?

For my Java apps with very long classpaths, I cannot see the main class specified near the end of the arg list when using ps. I think this stems from my Ubuntu system's size limit on /proc/pid/cmdline. How can I increase this limit?
For looking at Java processes jps is very useful.
This will give you the main class and jvm args:
jps -vl | grep <pid>
You can't change this dynamically, the limit is hard-coded in the kernel to PAGE_SIZE in fs/proc/base.c:
274 int res = 0;
275 unsigned int len;
276 struct mm_struct *mm = get_task_mm(task);
277 if (!mm)
278 goto out;
279 if (!mm->arg_end)
280 goto out_mm; /* Shh! No looking before we're done */
281
282 len = mm->arg_end - mm->arg_start;
283
284 if (len > PAGE_SIZE)
285 len = PAGE_SIZE;
286
287 res = access_process_vm(task, mm->arg_start, buffer, len, 0);
I temporarily get around the 4096 character command line argument limitation of ps (or rather /proc/PID/cmdline) is by using a small script to replace the java command.
During development, I always use an unpacked JDK version from SUN and never use the installed JRE or JDK of the OS no matter if Linux or Windows (eg. download the bin versus the rpm.bin).
I do not recommend changing the script for your default Java installation (e.g. because it might break updates or get overwritten or create problems or ...)
So assuming the java command is in /x/jdks/jdk1.6.0_16_x32/bin/java
first move the actual binary away:
mv /x/jdks/jdk1.6.0_16_x32/bin/java /x/jdks/jdk1.6.0_16_x32/bin/java.orig
then create a script /x/jdks/jdk1.6.0_16_x32/bin/java like e.g.:
#!/bin/bash
echo "$#" > /tmp/java.$$.cmdline
/x/jdks/jdk1.6.0_16_x32/bin/java.orig $#
and then make the script runnable
chmod a+x /x/jdks/jdk1.6.0_16_x32/bin/java
in case of copy and pasting the above, you should make sure that there are not extra spaces in /x/jdks/jdk1.6.0_16_x32/bin/java and #!/bin/bash is the first line
The complete command line ends up in e.g. /tmp/java.26835.cmdline where 26835 is the PID of the shell script.
I think there is also some shell limit on the number of command line arguments, cannot remember but it was possibly 64K characters.
you can change the script to remove the command line text from /tmp/java.PROCESS_ID.cmdline
at the end
After I got the commandline, I always move the script to something like "java.script" and copy (cp -a) the actual binary java.orig back to java. I only use the script when I hit the 4K limit.
There might be problems with escaped characters and maybe even spaces in paths or such, but it works fine for me.
You can use jconsole to get access to the original command line without all the length limits.
It is possible to use newer linux distributions, where this limit was removed, for example RHEL 6.8 or later
"The /proc/pid/cmdline file length limit for the ps command was previously hard-coded in the kernel to 4096 characters. This update makes sure the length of /proc/pid/cmdline is unlimited, which is especially useful for listing processes with long command line arguments. (BZ#1100069)"
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/6.8_Release_Notes/new_features_kernel.html
For Java based programs where you are just interested in inspecting the command line args your main class got, you can run:
jps -m
I'm pretty sure that if you're actually seeing the arguments truncated in /proc/$pid/cmdline then you're actually exceeding the maximum argument length supported by the OS. As far as I can tell, in Linux, the size is limited to the memory page size. See "ps ww" length restriction for reference.
The only way to get around that would be to recompile the kernel. If you're interested in going that far to resolve this then you may find this post useful: "Argument list too long": Beyond Arguments and Limitations
Additional reference:
ARG_MAX, maximum length of arguments for a new process
Perhaps the 'w' parameter to ps is what you want. Add two 'w' for greater output. It tells ps to ignore the line width of the terminal.

Resources