I am working to display users display name, date and time of login, and their default Bash shell. I can get each to print but I cannot find a way to get it to display line by line.
This is what I have tried to far. I have tried using that pipe, but so far putting them both in variables has been the closest thing yet.
#!/bin/bash
x="$(who | tr -s [:space:] | cut -d' ' -f1,3,4)"
y="$(cat /etc/passwd | tr -s [:print:] | cut -d':' -f7)"
echo $x $y
For every user I have to display this:
username date of login time of login default bash shell
UPDATE:
The answers to other questions combine a single string together, this question is asking how to combine multiple lines of the WHO command, with the users default bash shell (which again is multiple lines). That is why I am asking here.
My sample output is to display the username, time and date of login, and the default bash shell for every logged in user like the who command does (so basically I want to take the who command, cut what I want out of it, and then add the user's default bash shell to the end). I have the two commands that give that to me but I need the default bash shell to be added onto each user displayed by the "who" command. Right now the program prints out all the users logged on and then after it prints them all out it prints the default shell.
Here is a quick and dirty attempt.
who |
while read -r name _ time date _; do
printf "%-12s %-14s %-14s %s\n" \
"$name" "$time" "$date" \
"$(getent passwd "$name" | cut -d: -f7)"
done
I am guessing as to what the fields are and what widths you want for the columns; the who tool's output is very system-dependent.
Related
However, I want to be able to do history | grep "something" | tail -n 10 -- this command, over all past commands, should let me see the last 10 commands with some substring. However, this doesn't search over all terminals, over all tabs, over all time, ever. I use zsh and script-save all my terminals with test "$(ps -ocommand= -p $PPID | awk '{print $1}')" = 'script' || (script -F $HOME/bash_histories_with_outputs/$(date +"%d-%b-%y_%H-%M-%S")_shell.log) in the ~./bashrc, but am not exactly sure how to route all of these files to the history command (if that's the best way to do this).
My HISTFILESIZE is already large.
I've hit a wall after trying to find a solution to this issue. I have a file of 1000 lines from a csv that I need to use to create users within centos.
csv file is structured as username, first, last, gender, dob, country, color, fruits, OS, shell, permission
lines 601 - 1000 | Add users with the following requirements:
username
comment
shell
primary group must be their color
I have my shell script like this:
cat file.csv | cut -d, -f7 | tail -400 | while read group; do groupadd "$group"; done
cat file.csv | cut -d, -f1-3,7,10 | tail -400 | while read username first last color shell; do useradd "$username" -c "$first $last" -g "$color" -s "$shell"; done
When I run the first script, I get "groupapp: group 'color' already exists." I think mainly because it added the group the first time and when it went through the new lines, it stated it already exists. When I verify using /etc/group I do see the groups listed in there.
Now when I run the second script, I get "useradd: group ' ' does not exist". Like I stated when I looked in /etc/group the groups were there. What am I doing wrong?
For the "group already exists" problem, you could add sort -u into the pipeline.
For the useradd problem, see what the output of cut is:
$ echo '1,2,3,4,5,6,7,8,9,10' | cut -d, -f1-3,7,10
1,2,3,7,10
To split that into separate variables with the read command, you need to specify that the delimiter is comma:
cut -d, -f1-3,7,10 file.csv \
| tail -400 \
| while IFS="," read -r username first last color shell; do
useradd "$username" -c "$first $last" -g "$color" -s "$shell"
done
Notes:
cut can read files, don't need cat
you almost always want read -r
How - given USER ID as parameter, find out what is his name? The problem is to write a Bash script, and somehow use etc/passwd file.
The uid is the 3rd field in /etc/passwd, based on that, you can use:
awk -v val=$1 -F ":" '$3==val{print $1}' /etc/passwd
4 ways to achieve what you need:
http://www.digitalinternals.com/unix/linux-get-username-from-uid/475/
Try this:
grep ":$1:" /etc/passwd | cut -f 1 -d ":"
This greps for the UID within /etc/passwd.
Alternatively you can use the getent command:
getent passwd "$1" | cut -f 1 -d ":"
It then does a cut and takes the first field, delimited by a colon. This first field is the username.
You might find the SS64 pages for cut and grep useful:
http://ss64.com/bash/grep.html
http://ss64.com/bash/cut.html
I found this solution to build hash-values:
echo -n wicked | shasum | awk '{print $1}'
But this works only with string input. I don't know how to hanlde input as hex, for example if i want to build sha1-value of sha1-value.
upd: I just found out there is option -b for shasum but it produces wrong output. Does it expect bytes with reversed endianness?
upd2: for example: I do the following input:
echo -n 9e38cc8bf3cb7c147302f3e620528002e9dcae82 | shasum -b | awk '{print $1}'
The output is bed846bb1621d915d08eb1df257c2274953b1ad9 but according to the hash calculator the ouput should be 9d371d148d9c13050057105296c32a1368821717
upd3: the -b option seems not to work at all. There is no difference whether I apply this parameter or not, i get the same result.
upd4: the whole script lookes as follows. It doesn't work because the null-byte gets removed as i either assign or concatenate .
password="wicked"
scrumble="4d~k|OS7T%YqMkR;pA6("
stage1_hash=$(echo -n $password| shasum | awk '{print $1}')
stage2_hash=$(echo $(echo -n $stage1_hash | xxd -r -p | shasum | awk '{print $1}') | xxd -r -p)
token=$(./xor.sh $(echo -n $scrumble$(echo 9d371d148d9c13050057105296c32a1368821717 | xxd -r -p) | shasum | awk '{print $1}') $stage1_hash)
echo $token
You can use xxd -r -p to convert hexadecimal to binary:
echo -n 9e38cc8bf3cb7c147302f3e620528002e9dcae82 | xxd -r -p | shasum -b | awk '{print $1}'
Note that the output of this is 9d371d148d9c13050057105296c32a1368821717; this matches what I get from hashing 9e38cc8bf3cb7c147302f3e620528002e9dcae82 using hash calculator. It appears that the value you got from bash calculator was a results of a copy-paste error, specifically leaving off the final "2" in the hex string.
UPDATE: I'm not sure exactly what the entire script is supposed to do, but I can point out several problems with it:
Shell variables, command arguments, and c strings in general cannot contain null bytes. There are also situations where trailing linefeeds get trimmed, and IIRC some early versions of bash couldn't handle delete characters (hex 7F)... Basically, don't try to store binary data (as in stage2_hash) or pass it as arguments (as in ./xor.sh) in the shell. Pipes, on the other hand, can pass raw binary just fine. So store it in hex, then convert to binary with xxd -r -p and pipe it directly to its destination.
When you expand a shell variable ($password) or use a command substitution ($(somecommand)) without wrapping it in double-quotes, the shell does some additional parsing on it (things like turning spaces into word breaks, expanding wildcards to lists of matching filenames, etc). This is almost never what you want, so always wrap things like variable references in double-quotes.
Don't use echo for anything nontrivial and expect it to behave consistently. Depending on which version of echo you have and/or what the password is, echo -n "$password" might print the password without a linefeed after it, or might print it with "-n " before it and a linefeed after, might do something with any backslash sequences in the password, or (if the password starts with "-") interpret the password itself as more options to the echo command. Use printf "%s" "$password" instead.
Don't use echo $(somecommand) (or even printf "%s" "$(somecommand)"). The echo and $() are mostly canceling each other here, but creating opportunities for problems in between. Just use the command directly.
Clean those up, and if it doesn't work after the cleanup try posting a separate question.
openssl command may help you. see HMAC-SHA1 in bash
like:
echo -n wicked | openssl dgst -sha1
I am supposed to make a script that prints all sizes and file-names in the current directory, ordered by size, using the "set" command.
#!/bin/bash
touch /tmp/unsorted
IFS='#'
export IFS
ls -l | tr -s " " "#" | sed '1d' > /tmp/tempLS
while read line
do
##set probably goes here##
echo $5 $9 >> /tmp/unsorted
done < /tmp/tempLS
sort -n /tmp/unsorted
rm -rf /tmp/unsorted
By logic, this is the script that should work, but it produces only blank lines.
After discussion with my classmates, we think that the "set" command must go first in the while loop. The problem is that we cant understand what the "set" command does, and how to use it. Please help. Thank you.
ls -l | while read line; do
set - $line
echo $5 $9
done | sort -n
or simply
ls -l | awk '{print $5, $9}' | sort -n
Set manipulates shell variables. This allows you to adjust your current environment for specific situations, for example, to adjust current globbing rules.
Sometimes it is necessary to adjust the environment in a script, so that it will have an option set correctly later on. Since the script runs in a subshell, the options you adjust will have no effect outside of the script.
This link has a vast amount of info on the various commands and options available.