How does "less" command get stdin input? - linux

I'm just wondering about this problem:
if I can use something like "ls -al | less", less should have the ability of waiting for input from stdin. What I expected to happen is after running "less" command, the program hang up and wait for input(as a consequence of calling gets() or something like that.)
But why in fact it showed an error message "Missing filename ("less --help" for help)" end exited?
Thank you.

less command can check both argc>1 and stdin be associated with a file(not a tty).

The less command is not designed in that matter. When you execute a command in bash it will display all of the information at once. The less command is used to display the STDOUT of a command or the contents of a file one screen at a time.

$ ls -al | less
total 16
drwxrwxr-x 4 hdante hdante 4096 Nov 24 17:11 .
drwxr-xr-x 88 hdante hdante 4096 Mar 24 22:14 ..
drwxrwxr-x 2 hdante hdante 4096 Nov 25 01:55 new
drwxrwxr-x 3 hdante hdante 4096 Nov 24 18:27 old
(END)
It works. Something is wrong with your less. From less manual pages:
http://www.linuxmanpages.com/man1/less.1.php
https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/less.1.html
The manual describes the filename as optional.
Hints to diagnose your problem:
try alias | grep less, to see if the command is being modified
try set | grep LESS, and check the scripts being run by LESSCLOSE and LESSOPEN

Related

How to use wget with multithread and wildcards?

I want to use wget to download multiple files at once in a script using wildcards, like this:
wget -r -nd --no-parent --no-remove-listing $ftpUrl -l1 -A file1*.txt &
wget -r -nd --no-parent --no-remove-listing $ftpUrl -l1 -A file2*.txt &
wget -r -nd --no-parent --no-remove-listing $ftpUrl -l1 -A file3*.txt &
The problem is that wget downloads .listing file everytime and because there are multiple instances running, sometimes the file is being downloaded when another instance is reading it.
Is there a way to lock .listing file or ask wget to not download it (I can do it manually as the first command)? I don't understand how it reads this .listing file since it's not a plain list of the URLs, but rather something like this:
drwxr-xr-x 3 4015 4015 16384 Dec 14 21:23 .
drwxr-xr-x 4 4015 4015 4096 Dec 14 21:23 ..
-rw-r--r-- 1 4015 4015 327 Feb 15 2022 file1-bla.txt
-rw-r--r-- 1 4015 4015 10716 Feb 15 2022 file2-bla.txt
-rw-r--r-- 1 4015 4015 163 Feb 15 2022 file2-bla.txt
If I try to use -i .listing (or even if I rename .listing to list.txt and use -i list.txt) I get an error saying that the URLs are not valid or something.
RFC 959 stipulates that
LIST (LIST) This command causes a list to be sent from the server to the passive DTP. If the pathname specifies a directory or other
group of files, the server should transfer a list of files in the
specified directory. If the pathname specifies a file then the server
should send current information on the file. A null argument implies
the user's current working or default directory. The data transfer is
over the data connection in type ASCII or type EBCDIC. (The user must
ensure that the TYPE is appropriately ASCII or EBCDIC). Since the
information on a file may vary widely from system to system, this
information may be hard to use automatically in a program, but may be
quite useful to a human user.
Observe that it does not impose formal requirement what exactly will be returned.
drwxr-xr-x 3 4015 4015 16384 Dec 14 21:23 .
drwxr-xr-x 4 4015 4015 4096 Dec 14 21:23 ..
-rw-r--r-- 1 4015 4015 327 Feb 15 2022 file1-bla.txt
-rw-r--r-- 1 4015 4015 10716 Feb 15 2022 file2-bla.txt
-rw-r--r-- 1 4015 4015 163 Feb 15 2022 file2-bla.txt
This looks akin to output of ls -lah command, if you are interested in using that to form URL list acceptable by wget then you should take last column (excluding . and ..) and prefix them with URL of FTP server, if that URL is ftp://ftp.example.com and you got list as above then your list of URLs should look as follows
ftp://ftp.example.com/file1-bla.txt
ftp://ftp.example.com/file2-bla.txt
ftp://ftp.example.com/file3-bla.txt

How to separate output for each command generated by a bash file?

Let's say we have a bash script like the one bellow:
echo test
ls -alh
pwd
echo test2
So the file can have any number of commands on it each producing or not its own output.
Then the above file is run like this /bin/bash -xe test.sh which will produce the following output:
+ echo test
test
+ ls -alh
total 32
drwx------+ 6 daniels staff 204B Apr 3 23:33 .
drwxr-xr-x+ 64 daniels staff 2.1K Apr 4 01:53 ..
-rw-r--r--# 1 daniels staff 6.0K Apr 3 23:33 .DS_Store
drwxr-xr-x 5 daniels staff 170B Mar 15 17:03 Todo
-rw-r--r--# 1 daniels staff 282B Apr 3 20:39 test.py
-rw-r--r--# 1 daniels staff 97B Apr 4 01:52 test.sh
+ pwd
/Users/daniels/Desktop
+ echo test2
test2
Is there any way to parse the generated output reliable and figure out how to separate the output based on each command?
For the above example we should be able to separate and extract one group with:
+ echo test
test
another one with
+ ls -alh
total 32
drwx------+ 6 daniels staff 204B Apr 3 23:33 .
drwxr-xr-x+ 64 daniels staff 2.1K Apr 4 01:53 ..
-rw-r--r--# 1 daniels staff 6.0K Apr 3 23:33 .DS_Store
drwxr-xr-x 5 daniels staff 170B Mar 15 17:03 Todo
-rw-r--r--# 1 daniels staff 282B Apr 3 20:39 test.py
-rw-r--r--# 1 daniels staff 97B Apr 4 01:52 test.sh
etc.
I was thinking of parsing the output and look if the line starts with + then take that as the start of one command but then you can easily have something like echo + ok which will make this logic fail.
Another option would've been if we can modify the char that is outputted by /bin/bash -x so that instead of + to output something like https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text but looks like + is hardcoded in bash and not configurable.
Any ideas?
+ is not hard-coded, and this is readily described in man bash and under help set for -x:
-x After expanding each simple command, for command,
case command, select command, or arithmetic for
command, display the expanded value of PS4, fol‐
lowed by the command and its expanded arguments or
associated word list.
And here's a further description of PS4, also from man bash:
PS4 The value of this parameter is expanded as with PS1 and
the value is printed before each command bash displays
during an execution trace. The first character of PS4 is
replicated multiple times, as necessary, to indicate mul‐
tiple levels of indirection. The default is ``+ ''.
Here's an example:
$ PS4=$'\nAnd now, a word from '; set -x; date; uptime
And now, a word from date
Mon Apr 3 16:20:35 PDT 2017
And now, a word from uptime
16:20:35 up 65 days, 1:24, 6 users, load average: 1.20, 1.42, 1.37
You can use this to embed special markers or characters as you see fit.

Top Command Output is Empty when run from cron

I was trying to redirect the TOP command output in the particular file in every 5 minutes with the below command.
top -b -n 1 > /var/tmp/TOP_USAGE.csv.$(date +"%I-%M-%p_%d-%m-%Y")
-rw-r--r-- 1 root root 0 Dec 9 17:20 TOP_USAGE.csv.05-20-PM_09-12-2015
-rw-r--r-- 1 root root 0 Dec 9 17:25 TOP_USAGE.csv.05-25-PM_09-12-2015
-rw-r--r-- 1 root root 0 Dec 9 17:30 TOP_USAGE.csv.05-30-PM_09-12-2015
-rw-r--r-- 1 root root 0 Dec 9 17:35 TOP_USAGE.csv.05-35-PM_09-12-2015
Hence i made a very small (1 line) shell script for this, so that i can run in every 5 minutes via cronjob.
Problem is when i run this script manually then i can see the output in the file, however when this script in running automatically, file is generating in every 5 minutes but there is no data (aka file is empty)
Can anyone please help me on this?
I now modified the script and still it's the same.
#!/bin/sh
PATH=$(/usr/bin/getconf PATH)
/usr/bin/top -b -n 1 > /var/tmp/TOP_USAGE.csv.$(date +"%I-%M-%p_%d-%m-%Y")
I met the same problem as you.
Top command with -b option must be added.Saving top output to variable before we use it.
the scripts are below
date >> /tmp/mysql-mem-moniter.log
MEM=/usr/bin/top -b -n 1 -u mysql
echo "$MEM" | grep mysql >> /tmp/mysql-mem-moniter.log
Most likely the environment passed to your script from cron is too minimal. In particular, PATH may not be what you think it is (no profiles are read by scripts started from cron).
Place PATH=$(/usr/bin/getconf PATH) at the start of your script, then run it with
/usr/bin/env -i /path/to/script
Once that works without error, it's ready for cron.

Automatically launching Firefox from terminal using at command

I am a beginner at linux and really enthusiastic to learn the OS. I am trying to launch Firefox(or any other software like Evince) from the command line as follows:
[root#localhost ~]# at 1637
[root#localhost ~]# at> firefox
[root#localhost ~]# at> ^d
The job gets scheduled without any error. But at the specified time it does not run.
I also tried giving the following path:
[root#localhost ~]# at 1637
[root#localhost ~]# at> /usr/bin/firefox
[root#localhost ~]# at> ^d
Still no result. But When I try to use echo to display a text on the screen it appears at the specified time as desired. What might be the issue?
I think you have not set DISPLAY. at will run in separate shell where display is not set.
try the following code.
dinesh:~$ at 2120
warning: commands will be executed using /bin/sh
at> export DISPLAY=:0
at> /usr/bin/firefox > firefox.log 2>&1
at> <EOT>
job 7 at Tue Mar 11 21:20:00 2014
If it is still failing check firefox.log for more information.
1) Its not always recommended to run things as root
2) You can also try ./firefox if you are in the current directory of firefox. In linux you need to pay attention to your path variable. Unless . (the current directory) is in your path you will have to type ./program if the program is in the same directory as you.
Also you need to pay attention to file permissions: In linux you have read-write-eXecute access.
ls -l will do a list of directories and show the file permissions:
drwxr-xr-x 10 user staff 340 Oct 6 2012 GlassFish_Server/
drwx------# 15 jeffstein staff 510 Oct 6 15:01 Google Drive/
drwxr-xr-x 20 jeffstein staff 680 May 14 2013 Kindle/
drwx------+ 67 jeffstein staff 2278 Jan 26 14:22 Library/
drwx------+ 19 jeffstein staff 646 Oct 23 18:28 Movies/
drwx------+ 15 jeffstein staff 510 Jan 3 20:29 Music/
drwx------+ 90 jeffstein staff 3060 Mar 9 20:23 Pictures/
drwxr-xr-x+ 6 jeffstein staff 204 Nov 3 21:16 Public/
drwxr-xr-x 22 jeffstein staff 748 Jan 14 2012 androidTools/
-rwxrwxrwx 1 jeffstein staff 1419 Aug 28 2013 color.sh*
This is an example of ls -l here you can see color.sh has -rwxrwxrwx that means that anybody can read or write or run the file.
Without actually knowing where you installed firefox however I can't be of more help but these are some small pointers which might help.
try finding where firefox is actually installed using "whereis firefox" command.
Then try using that path in at command.
In order to get directions on how to use a command type:
man at
this will display the "manual"
DESCRIPTION
The at and batch utilities read commands from standard input or a speci-
fied file. The commands are executed at a later time, using sh(1).
at executes commands at a specified time;
atq lists the user's pending jobs, unless the user is the superuser;
in that case, everybody's jobs are listed;
atrm deletes jobs;
batch executes commands when system load levels permit; in other words,
when the load average drops below _LOADAVG_MX (1.5), or the value
specified in the invocation of at run.
So obviously you need to schedule a job with at and you can see if it worked with atq
Read the manual and it should help - if i have more time I'll write you a quick example.

Why doesn't grep work if a file is not specified?

I have some problem with the Linux grep command, it don't work !!!
I am trying the following test on my Ubuntu system:
I have create the following folder: /home/andrea/Scrivania/prova
Inside this folder I have created a txt file named prova.txt and inside this file I have write the string test and I have save it
In the shell I have first access the folder /home/andrea/Scrivania/prova and so I have launched the grep command in the following way:
~/Scrivania/prova$ grep test
The problem is that the cursor continues to blink endlessly and cannot find NOTHING! Why? What is the problem?
You've not provided files for the grep command to scan
grep "test" *
or for recursive
grep -r "test" *
Because grep searches standard input if no files are given. Try this.
grep test *
You are not running the command you were looking for.
grep test * will look for test in all files in your current directory.
grep test prova.txt will look for test specifically in prova.txt
(grep test will grep the test string in stdin, and will not return until EOF.)
You need to pipe in something to grep - you cant just call grep test without any other arguments as it is actually doing nothing. try grep test *
Another use for grep is to pipe in a command
e.g. This is my home directory:
drwx------+ 3 oliver staff 102 12 Nov 21:57 Desktop
drwx------+ 10 oliver staff 340 17 Nov 18:34 Documents
drwx------+ 17 oliver staff 578 20 Nov 18:57 Downloads
drwx------# 12 oliver staff 408 13 Nov 20:53 Dropbox
drwx------# 52 oliver staff 1768 11 Nov 12:05 Library
drwx------+ 3 oliver staff 102 12 Nov 21:57 Movies
drwx------+ 5 oliver staff 170 17 Nov 10:40 Music
drwx------+ 3 oliver staff 102 20 Nov 19:17 Pictures
drwxr-xr-x+ 4 oliver staff 136 12 Nov 21:57 Public
If i run
l | grep Do
I get the result
drwx------+ 10 oliver staff 340 17 Nov 18:34 Documents
drwx------+ 17 oliver staff 578 20 Nov 18:57 Downloads
remember to pipe the grep command
From grep man page:
Grep searches the named input FILEs (or standard input if no files
are
named, or the file name - is given) for lines containing a match to the
given PATTERN.
If you don't provide file name(s) for it to use, it will try to read from stdin.
Try grep test *
As per GNU Grep 3.0
A file named - stands for standard input. If no input is specified,
grep searches the working directory . if given a command-line
option specifying recursion; otherwise, grep searches standard input.
So for OP's command, without any additional specification, grep tries to search in standard input, which is not actually provided there.
A simple approach is grep -r [pattern], as per the above, to specify recursion with -r and search in current directory and sub-directories.
Also note that wildcard * only includes files, not directories. If used, a prompt might be shown for hint:
grep: [directory_name]: Is a directory

Resources