Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
bash script how to determine if a folder is a home directory
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Portage & Programming
View previous topic :: View next topic  
Author Message
littletux
n00b
n00b


Joined: 08 Dec 2003
Posts: 74

PostPosted: Mon Mar 20, 2017 12:52 am    Post subject: bash script how to determine if a folder is a home directory Reply with quote

I am searching for a unambiguously sign that I could use to determine if a directory is a users home directory.
I want determine if a folder path is a directory that is used as a users home directory.
The unambiguously sign should let me decide with a if statement in my script if the path I have choosed with a dialog --dselect box is a folder used as users home or not.
Any suggestions?


I had a inspiration
my solution is
Code:
ls -n
give me the uid gid and if this values is 1000 or bigger it is a users home
Back to top
View user's profile Send private message
khayyam
Watchman
Watchman


Joined: 07 Jun 2012
Posts: 6227
Location: Room 101

PostPosted: Mon Mar 20, 2017 2:28 am    Post subject: Reply with quote

littletux ...

perhaps the following would be more programatic:

Code:
% awk -F: '{if ($6~/.home.*/ && $3>=1000) print $6}' /etc/passwd

Of course if your users are not in /home then the first test could be made more robust. Also, you could test further fields (ie, gid, or shell) if needed.

If your script needs to do something with these items, then:

Code:
#!/bin/bash
set -e

userarray=($(awk -F: '{if ($6~/.home.*/ && $3>=1000) print $6}' /etc/passwd))

for i in "${userarray[@]}" ; do
  echo "$i"
done

HTH & best ... khay
Back to top
View user's profile Send private message
littletux
n00b
n00b


Joined: 08 Dec 2003
Posts: 74

PostPosted: Mon Mar 20, 2017 3:27 am    Post subject: Reply with quote

Thanks for answer, but your solution is not possible in my scenario, because my script must run on a livesystem at boottime, so the informations you suggest are not avaiable, because the path is as you said not under /home.
So I think the only way to identify is that the uid gid is equal or bigger 1000
Back to top
View user's profile Send private message
khayyam
Watchman
Watchman


Joined: 07 Jun 2012
Posts: 6227
Location: Room 101

PostPosted: Mon Mar 20, 2017 3:54 am    Post subject: Reply with quote

littletux wrote:
Thanks for answer, but your solution is not possible in my scenario, because my script must run on a livesystem at boottime, so the informations you suggest are not avaiable, because the path is as you said not under /home. So I think the only way to identify is that the uid gid is equal or bigger 1000

littletux ... well, firstly I'm not sure what you mean by "livesystem". I assume that whatever directory is hosting home directories is mounted relative to rootfs ... and so /etc would be there. If not then how are these users being authenticated, or $HOME asigned? If this is done via ldap, or AD, then ok, none of those fields exist in /etc/passwd, but that doesn't seem to be what you're saying, your saying /etc is not accessable.

best ... khay
Back to top
View user's profile Send private message
littletux
n00b
n00b


Joined: 08 Dec 2003
Posts: 74

PostPosted: Mon Mar 20, 2017 10:30 am    Post subject: Reply with quote

With livesystem is meant, I will use this script on a LIVECD. the script will mount all linux formated partitions under /mnt/(partitionname) and then i can choose with this dialogbox a folder i want as my home. If this is not a valid home the dialogbox pop up again for to rechoose a valid home. If choosen a valid home, i have the correct uid gid and username. So I can create directory /home/(username). After that I do a bind mount from real path to this newly created directory and create this user and give him the existing directory
Back to top
View user's profile Send private message
NeddySeagoon
Administrator
Administrator


Joined: 05 Jul 2003
Posts: 54237
Location: 56N 3W

PostPosted: Mon Mar 20, 2017 11:02 am    Post subject: Reply with quote

littletux,

You need to use the etc that is is /mnt/rootfs_name/.
Then you can read /mnt/rootfs_name/etc/fstab to assemble your system under the liveCD mount point and know which filesystem goes where.
_________________
Regards,

NeddySeagoon

Computer users fall into two groups:-
those that do backups
those that have never had a hard drive fail.
Back to top
View user's profile Send private message
littletux
n00b
n00b


Joined: 08 Dec 2003
Posts: 74

PostPosted: Mon Mar 20, 2017 12:57 pm    Post subject: Reply with quote

Thanks but this i'm sure, will definitely not work. It could be work if the fstab only uses labels or uuid entrys, but if /dev/sdx entrys are given in fstab, this method 100% will fail. I will now do a double featured check. the first condition I check is the bigger as 1000 uid gid, the second check that must be correct on same folder, it must have an existing .config folder inside. This way I can be nearly 100% sure, a folder is a userhome directory

another problem with the fstab solution is that not all /mnt/rootfs_name/ must contain etc because a partition containing userdirectories could be mounted under /home and those a partition contains no etc. it only contains 1 or more home directories
Back to top
View user's profile Send private message
cboldt
Veteran
Veteran


Joined: 24 Aug 2005
Posts: 1046

PostPosted: Mon Mar 20, 2017 1:25 pm    Post subject: Reply with quote

Code:
UID=$(stat -c %u <target file or directory>)


No additional manipulation required. You could even drop the `stat -c %u` command directly into your comparison, simple enough to understand the logic at a glance.

Code:
if [ `stat -c %u <target_dir>` -gt 1000 ]; then
  do your thing
fi


Caution about absence of error checking, e.g., non-existent target_dir

Edit to add another possible error - depends on your system, but I have users here with UID < 1000. Old convention, I know. Your system may well be fine on this count. Easy enough to check UID for all directories (and files) right off /home.
Back to top
View user's profile Send private message
littletux
n00b
n00b


Joined: 08 Dec 2003
Posts: 74

PostPosted: Mon Mar 20, 2017 1:59 pm    Post subject: Reply with quote

It's good you have answered me that, because, now i remember, some systems have had uid from 500 in the past, so i will change my script to check id's from this value. And probably I will use the stat command to determine the id's because it's more elegant than ls -n | awk '{print... :D
Back to top
View user's profile Send private message
cboldt
Veteran
Veteran


Joined: 24 Aug 2005
Posts: 1046

PostPosted: Mon Mar 20, 2017 2:21 pm    Post subject: Reply with quote

It shouldn't be a terribly long list, try `stat -c "%u %n" /*/*`

The shorter list of `stat -c "%u %n /*` shows "all zeros" for me, so nothing interesting or informative until I get to the next layer.

Edit to add (I am not an awk-ophobe)

Code:
stat -c "%u %n" /*/* | awk '$1 > 500'
Back to top
View user's profile Send private message
khayyam
Watchman
Watchman


Joined: 07 Jun 2012
Posts: 6227
Location: Room 101

PostPosted: Mon Mar 20, 2017 7:03 pm    Post subject: Reply with quote

cboldt wrote:
Edit to add (I am not an awk-ophobe)

Code:
stat -c "%u %n" /*/* | awk '$1 > 500'

cboldt ... you'd probably want '$1 >= 500', because otherwise 500 doesn't qualify, and this is what I would expect "uid from 500" to include.

best ... khay (also not an awk-ophobe ;)
Back to top
View user's profile Send private message
cboldt
Veteran
Veteran


Joined: 24 Aug 2005
Posts: 1046

PostPosted: Mon Mar 20, 2017 7:14 pm    Post subject: Reply with quote

Okay, $1 > 499 then ...
Back to top
View user's profile Send private message
szatox
Advocate
Advocate


Joined: 27 Aug 2013
Posts: 3136

PostPosted: Mon Mar 20, 2017 9:53 pm    Post subject: Reply with quote

littletux, I have no idea what you're doing, but I'm pretty sure it's totally insane.
Why won't you slow down, take a deep breath, and then tell us what are you trying to actually achieve?

E.g. why you want to know if a directory is someone's home? Usually you only need your own home directory, and you can expand $HOME or even ~ to get this. You surely knew that already, which leads to the next question:
From who's perspective are you looking at the system?
What is the purpose of that LiveCD?
Back to top
View user's profile Send private message
littletux
n00b
n00b


Joined: 08 Dec 2003
Posts: 74

PostPosted: Mon Mar 20, 2017 11:15 pm    Post subject: Reply with quote

The purpose is I want a LIVECD that allows me to work with an existing home directory and work with it in a simple way . Its something similar to a persistent home, but i can use it for all disks on any disk that has somehwere inside a users home. Yes maybe it's a little bit crazy but im sure I have in short a simple and good solution for this.

And yes maybe im a little bit crazy. I also have created a script that lets me install more than one nvidia drivers at same time on the LIVECd's system. Another script then detects on the fly at boot which driver should used.
In this time I have installed the nvidia drivers in version 304.135 340.102 378.13 at the same time. Really I can not use more than one at the same boot because this is not provided by nvidia, but i have on all PC hardware that have a card that is supported from one of this drivers fully 3D support . This means concret that all cards from Geforce 6 to the newest will be fully supported

So yes im a little bit crazy
Back to top
View user's profile Send private message
szatox
Advocate
Advocate


Joined: 27 Aug 2013
Posts: 3136

PostPosted: Tue Mar 21, 2017 6:55 pm    Post subject: Reply with quote

The bit on multiple drivers is pretty straight-forward in it's purpose, but I don't see how it is related to your home discovery.

How much control you have over those home dirs? Can you e.g. create a tag file inside? like $HOME/.this_is_my_home_directory
What if there are several users? Are you happy picking the first one of them?
Why not just search for /etc/fstab and /etc/password? Separate /etc/ takes too much work for too little benefit, so you can just scan all volumes for those files in known locations.
Also, what if you encounter multiboot system?
Back to top
View user's profile Send private message
littletux
n00b
n00b


Joined: 08 Dec 2003
Posts: 74

PostPosted: Tue Mar 21, 2017 10:05 pm    Post subject: Reply with quote

Some of your questions you have I also asked me myself, and I have decided that it is enough for me I can choose only one of more existant homes in a multiboot environement. and I also has decided it is enough I can only choose one user at boot in a multiuser environement. If I later decide I need a nore complex solution I will try to implement it but in moment im happy as is.

here is my working solution for now

https://raw.githubusercontent.com/mundis/scripts/master/livecd_related/use_existing_home/etc/init.d/create-user
Back to top
View user's profile Send private message
khayyam
Watchman
Watchman


Joined: 07 Jun 2012
Posts: 6227
Location: Room 101

PostPosted: Wed Mar 22, 2017 7:50 am    Post subject: Reply with quote

littletux wrote:
here is my working solution for now

https://raw.githubusercontent.com/mundis/scripts/master/livecd_related/use_existing_home/etc/init.d/create-user

littletux ... "you're doing it wrong" ;) ... anyhow, some comments/pointers:

littletux wrote:
Code:
PARTITIONS=(`blkid | grep -v swap | grep -v vfat| grep -v ntfs | grep -v crypto_LUKS | grep -iv bios | grep PARTUUID | awk '{print $1}' | sed 's/://g'`)

You're a pipaholic, hehe, awk doesn't just print fields, you can do all of the above with only one pipe:

Code:
partitions=($(blkid | awk '!/(swap|vfat|ntfs|crypto_LUKS|bios)/&&/PARTUUID/{gsub(/:/,"") ; print $1}')

Also, you should get in the habit of using '$()' for command substitution, backticks are depreciated (not to mention easily missed). Note that you might want to add 'swsuspend', 'LVM2_member', and perhaps others, to the list of exclusions (or, better still, expand the blkid command to include ' -t TYPE=', or '-n list', etc, so as to only provide the required output).

littletux wrote:
Code:
CRYPTODEVS=(`blkid | grep crypto_LUKS | awk '{print $1}' | sed 's/[:]*$//'`)
CRYPTONAMES=(`blkid | grep crypto_LUKS | awk '{print $1}' | sed 's/[:]*$//' | sed 's/\/dev\///g'`)
ENCRYPDEVS=(`echo ${CRYPTODEVS[@]} | sed 's/dev/dev\/mapper/g'`)

Here (and elsewhere) you need to use parameter expansion (and, perhaps, limit the blkid output to only the required fields):

Code:
# blkid -o device -t TYPE="crypto_LUKS"
/dev/sda2
# cryptodevs=($(blkid -o device -t TYPE="crypto_LUKS"))
# encrypdevs=${cryptodevs[@]#/*/*}
# echo $encrypdevs
sda2

Actually, that looks wrong to me, because in the above you're expecting 'cryptodevs' to return /dev/mapper, but that doesn't seem to be the case. Anyhow, it might be better to limit the number of calls to blkid to one, and parse out all data from that one call (or at least reduce the number of calls to a minimum with the use of parameter expansion).

HTH & best ... khay
Back to top
View user's profile Send private message
cboldt
Veteran
Veteran


Joined: 24 Aug 2005
Posts: 1046

PostPosted: Wed Mar 22, 2017 11:23 am    Post subject: Reply with quote

Piling on, sort of, grep does facilitate multiple excludes in one command. Khayyam's point about awk is well taken, but at least to me, "internalizing" awk takes a long time, compared with doing so for "grep." I can compose grep without referring to the man page, not so much with awk.

Code:
grep -v -e exclude1 -e exclude2 -e exclude3 <file>


And with respect to the "backtick" "$()" structure, both are useful in the long run, in particular for nested commands. Something makes me think I have at least one instance where $() chokes too, for other reasons. That said, I have been making an effort to prefer $() over backticks as I compose script routines. It is easier to see.
Back to top
View user's profile Send private message
cboldt
Veteran
Veteran


Joined: 24 Aug 2005
Posts: 1046

PostPosted: Wed Mar 22, 2017 11:28 am    Post subject: Reply with quote

The parsing chore might be made easier with "lsblk" compared with "blkid" This is from `man blkid`

Code:
       It is recommended to use lsblk(8) command to get information about block devices rather than blkid.  lsblk(8) provides more information, better control on output formatting and it does not require root permissions to get actual information.

       When device is specified, tokens from only this device are displayed.  It is possible to specify multiple device  arguments  on  the command line.  If none is given, all devices which appear in /proc/partitions are shown, if they are recognized.

       Note that blkid reads information directly from devices and for non-root users it returns cached unverified information.  It is better to use lsblk --fs to get a user-friendly overview of filesystems and devices.  lsblk(8) is also easy to use in  scripts.   blkid is mostly designed for system services and to test libblkid functionality.


lsblk has some built-in "exclude from the listing" functionality

Code:
-e, --exclude list
              Exclude the devices specified by the comma-separated list of major  device  numbers.   Note  that  RAM  disks  (major=1)  are excluded by default.  The filter is applied to the top-level devices only.
Back to top
View user's profile Send private message
littletux
n00b
n00b


Joined: 08 Dec 2003
Posts: 74

PostPosted: Wed Mar 22, 2017 12:30 pm    Post subject: Reply with quote

Thanks for all feedback and tips on how I could do something better. They maybe can be very helpful for next scriptings.

@khayyam
Quote:
Actually, that looks wrong to me, because in the above you're expecting 'cryptodevs' to return /dev/mapper, but that doesn't seem to be the case.


No you see that wrong I expect that ENCRYPDEVS needs to be a mapper device because I do as followed with CRYPTODEVS,
Code:
        for i in $(seq 0 $((${#CRYPTODEVS[*]} -1 )));do
                cryptsetup luksOpen ${CRYPTODEVS[i]} ${CRYPTONAMES[i]}
        done


the fault is I have noticed it should not be ENCRYPDEVS it should be DECRYPTEDDEVS sorry for my bad english :oops:

The only real problem that maybe could happen if lvm devices would be exist my script would fail

I know some things are not really finished, but for first it works, and if I use it on a Computer and it fails, I can analyse why it fails and then maybe implement an addition that also considered this case


Last edited by littletux on Wed Mar 22, 2017 12:43 pm; edited 1 time in total
Back to top
View user's profile Send private message
NeddySeagoon
Administrator
Administrator


Joined: 05 Jul 2003
Posts: 54237
Location: 56N 3W

PostPosted: Wed Mar 22, 2017 12:35 pm    Post subject: Reply with quote

littletux,

You can add all the error handling you can think about and the script will be fine for you.
As soon as you give it so someone else, they will do things you didn't think about and it will break.
Thats the way of the world.
_________________
Regards,

NeddySeagoon

Computer users fall into two groups:-
those that do backups
those that have never had a hard drive fail.
Back to top
View user's profile Send private message
littletux
n00b
n00b


Joined: 08 Dec 2003
Posts: 74

PostPosted: Wed Mar 22, 2017 12:48 pm    Post subject: Reply with quote

@NeddySeagoon

Yes I know, and all that uses a script from another person should know that all work in opensource world is not perfect and could break something. Anyway if nobody would release his code, no matter if its perfect or not linux would not exist
Back to top
View user's profile Send private message
khayyam
Watchman
Watchman


Joined: 07 Jun 2012
Posts: 6227
Location: Room 101

PostPosted: Wed Mar 22, 2017 10:05 pm    Post subject: Reply with quote

cboldt wrote:
Piling on, sort of, grep does facilitate multiple excludes in one command. Khayyam's point about awk is well taken, but at least to me, "internalizing" awk takes a long time, compared with doing so for "grep." I can compose grep without referring to the man page, not so much with awk.

Code:
grep -v -e exclude1 -e exclude2 -e exclude3 <file>

cboldt ... you needn't do that, {e,}grep can be provide one expression:

Code:
# blkid | grep -Ev '(swap|vfat|ntfs|crypto_LUKS|bios)'

The point is, you still need to process the output further (sed for string replacement, awk for the field, etc) and that can be avoided. My general rule is to do as much with one command as is possible, so eg, 'cat foo | grep ba' is better served by 'grep ba foo', awk is often the go-to for such processing because (as is the case above) it's already needed in the pipeline, and because matching, inversion, string replacement, field selection, are all there. I don't think you would have too much problems understanding the above awk, because much of it you probably know from other tools (is '!//', '(|)', '&&', 'gsub//,'.

cboldt wrote:
And with respect to the "backtick" "$()" structure, both are useful in the long run, in particular for nested commands. Something makes me think I have at least one instance where $() chokes too, for other reasons. That said, I have been making an effort to prefer $() over backticks as I compose script routines. It is easier to see.

You shouldn't have any problems nesting '$()', any issues are probably to do with quoting, I don't think I've ever had a situation in which I needed to use a backtick.

cboldt wrote:
The parsing chore might be made easier with "lsblk" compared with "blkid" [...] lsblk has some built-in "exclude from the listing" functionality.

I agree, but that is the least of their problems, there are far too many things taken for granted, and not a single test condition exists to check if [ -n $var ] before doing something with $var. I also just noticed (my bad) the shebang, and so really this needs to be posix (as bash arrays are used) and/or run from elsewhere (ie, inittab, or local.d as '#!/bin/bash').

littletux wrote:
khayyam wrote:
Actually, that looks wrong to me, because in the above you're expecting 'cryptodevs' to return /dev/mapper, but that doesn't seem to be the case.

No you see that wrong I expect that ENCRYPDEVS needs to be a mapper device because I do as followed with CRYPTODEVS [...] the fault is I have noticed it should not be ENCRYPDEVS it should be DECRYPTEDDEVS sorry for my bad english

No, I see it correctly, see the output I provided above.

NeddySeagoon wrote:
You can add all the error handling you can think about and the script will be fine for you. As soon as you give it so someone else, they will do things you didn't think about and it will break. Thats the way of the world.

I disagree, all error handling is for the purpose of the internal logic of the script, it may fail (here, or elsewhere), but that is what all the test conditions are for ... that is does fail (rather than run 'command $foo $ba'). That's the rule of repair: "When you must fail, fail noisily and as soon as possible."

best ... khay
Back to top
View user's profile Send private message
NeddySeagoon
Administrator
Administrator


Joined: 05 Jul 2003
Posts: 54237
Location: 56N 3W

PostPosted: Wed Mar 22, 2017 10:32 pm    Post subject: Reply with quote

khayyam,

That page is a wee gem. Bookmarked.
Thank you.
_________________
Regards,

NeddySeagoon

Computer users fall into two groups:-
those that do backups
those that have never had a hard drive fail.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Portage & Programming All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum