When you first log in to a Unix system from a terminal, the system normally starts a login shell. A login shell is typcally the top-level shell in the “tree” of processes that starts with the init process. Many characteristics of processes are passed from parent to child process down this “tree” — especially environment variables, such as the search path. The changes you make in a login shell will affect all the other processes that the top-level shell starts — including any subshells.

So, a login shell is where you do general setup that’s done only the first time you log in — initialize your terminal, set environment variables, and so on. […]

So you could think about a login shell as a shell that is started at startup by the init process (or systemd nowadays). Or as a shell that logs you into the system by your providing a username and a password. A nonlogin shell, by contrast, is a shell that is invoked without logging anybody in.

Is My Current Shell a Login Shell?

There are two ways to check if your current shell is a login shell: First, you can check the output of echo $0: if it starts with a dash (like -bash), it’s a login shell. Be aware, however, that you can start a login shell with bash --login, and echo $0 will output just bash without the leading dash, so this is not a surefire way of find out if you are running a login shell.

The Difference Between Login and Nonlogin That Actually Matters

Practically speaking, the difference between a login shell and a nonlogin shell is in the configuration files that Bash reads when it starts up. In particular, according to man bash:

[…] it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable.

You can observe this behavior by putting echo commands in /etc/profile, ~/.bash_profile, ~/.bash_login and ~/.profile. Upon invoking bash --login you should see:

echo from /etc/profileecho from ~/.bash_profile$

If the shell is a nonlogin shell, Bash reads and executes commands from ~/.bashrc. Since we are starting a nonlogin shell from within a login shell, it will inherit the environment. Sometimes, this will lead to confusion when we inadvertantly get a login shell, and find out that our configuration from ~/.bashrc is not loaded. This is why many people put something like the following in their .bash_profile:

[[ -r ~/.bashrc ]] && source ~/.bashrc

This test whether .bashrc is readable and then sources it.

Why You Sometimes Want a Login Shell

When you switch users using su you will take the environment of the calling user with you. To prevent this, you should use su - which is short for su --login. This acts like a clean login for a new user, so the environment will not be cluttered with values from the calling user. Just as before, a login shell will read /etc/profile and the .bash_profile of the user you are switching to, but not its .bashrc. This post on StackOverflow shows why you might want to prefer to start with a clean environment (spoiler: your $PATH might be “poisened”).

Conclusion

In this article we saw that the main difference between a login and a nonlogin shell are the configuration files that are read upon startup. We then looked at what the benefits are of a login shell over a nonlogin shell.

You have a drive that you want to encrypt and use in Linux and other OSes. Then Veracrypt, the successor of Truecrypt, is a good choice. The prerequisite for this tutorial is that you already have created a partition on a drive. See my previous blog post on how to accomplish that. Creating a volume on a partition with data on it will permanently destroy that data, so make sure you are encrypting the correct partition (fdisk -l is your friend).

Encrypt a volume interactively from the command line using Veracrypt…

(The # sign at the beginning of the code examples indicates that the command should be executed as root. You can either use su - or sudo to accomplish this.)

# veracrypt -t --quick -c /dev/sdXX

-t is short for --text (meaning you don’t want the GUI) and should always be used first after the command name. The --quick option is explained in the docs:

If unchecked, each sector of the new volume will be formatted. This means that the new volume will be entirely filled with random data. Quick format is much faster but may be less secure because until the whole volume has been filled with files, it may be possible to tell how much data it contains (if the space was not filled with random data beforehand). If you are not sure whether to enable or disable Quick Format, we recommend that you leave this option unchecked. Note that Quick Format can only be enabled when encrypting partitions/devices.

So, using --quick is less secure, but not specifying it could take (a lot) longer, especially on traditional hard drives (we’re talking hours for 500GB).

Finally, the -c or --create command allows us to specify on which partition we want to create a veracrypt volume. Make sure you change the /dev/sdXX from the example above to the appropriate output of fdisk -l (for example, /dev/sdc1).

The missing $HOME/.lessrc

I often wondered how I could make certain options for less permanent, like -I, for example, which will make search case insensitive. In GNU/Linux, preferences are often stored in rc files. For vim we have .vimrc, for Bash .bashrc, etc:

See the overall progress of rsync

By default, rsync will show the progress of the individual files that are being copied. If you want the overall progress, you have to add some flags:

$ rsync -a --info=progress2 --no-i-r src dst

--info=progress2 shows the total transfer progress. (To see all available options for --info, execute rsync --info=help). --no-i-r is short for --no-inc-recursive and disables incremental recursion, forcing rsync to do a complete scan of of all directories before starting the file transfer. This is needed to get an accurate progress report, otherwise rsync doesn’t know how much work is left.

Human-readable output can be obtained by passing the -h or --human-readable option.

Say we bought an external hard drive to back up some stuff from a crashed computer. We can use a Live USB to get at the data and put the data on the external hard drive. Because the data needs to be accessible by Windows, we are going to use format the drive with NTFS.

Create partition

Connect the external hard disk to your computer. Use sudo fdisk -l to find the device name. Output should look something like this:

As can been seen above, the name of the device is /dev/sdb. We use to name to run fdisk:

$ sudo fdisk /dev/sdb

Notice how we use the name of the device, and not the name of the partition (so /dev/sdb without any numbers attached at the end).

After entering the command above, an interactive menu will be facing you. Type a letter and press Enter to confirm. Changes will only be applied when you type w, so if you make a mistake, just stay calm and press q and you will exit fdisk with your pending changes discarded.

Delete all your existing partitions by pressing d. Depending on the amount of partitions, you might have to repeat this several times. If you want to check the current partition table, press p.

After all old partitions are deleted, add a new partition by pressing n. If you just want to create a single partition on your drive, accept all the defaults by pressing Enter on each prompt. This will leave you with a single partition that will take up all space on the drive.

Back in the main menu, type t to change the partition type. Press L to see all partitions types. Here we are going to choose 7 (HPFS/NTFS/exFAT). “The partition type […] is a byte value intended to specify the file system the partition contains and/or to flag special access methods used to access these partitions” (source). Linux does not care about the partition type, but Windows does, so we have to change it.

Press w to write your changes to the disk and exit fdisk.

Format partition with NTFS

Now we create the actual NTFS file system on the drive:

$ sudo mkfs.ntfs -Q -L label /dev/sdX1

(If you don’t have mkfs.ntfs installed, use your distro’s package manager to install it (on Arch Linux it’s in a package called ntfs-3g)).

Breakdown:

-Q is the same as --quick, -f or --fast. This will perfom a quick format, meaning that it will skip both zeroing of the volume and and bad sector checking. So obviously, leave this option out if you want the volume to be zeroed or you want error checking. Depending on the size of your partition, this might take quite a while.

-L is the same as --label: it’s the identifier you’ll see in Windows Explorer when your drive is connected.

dev/sdX1: change the X to the actual letter of your drive we found earlier in this tutorial. You always format a partition, not a drive, so make sure that you put the correct number of the partition you want formatted at the end.

Check the output and find the device name of the USB (for instance /dev/sdc). Make sure this device is not mounted, otherwise the next command will fail. Also make sure you note the device name, and not a partition (indicated by a numeral at the end: /dev/sdc1, for example).

Copy Arch Linux image to USB drive

of, likewise, points to the output file, which is a device in this case. Note that /dev/sdX needs to be replaced with the device name we found in the previous step.

bs=64K indicates the block size, which means that dd will read and write up to 64K bytes at a time. The default is 512 bytes. It really depends what the optimal block size is, but several sources indicate that 64K is a good bet on somewhat modern to modern hardware.

oflag stands for “output flag”. The sync flag will make sure that all data is written to the USB stick when the dd command exits, so it will be safe to remove the USB stick.

Notice that the device does not need to be partitioned or empty before this operation. When dd writes to a device rather than a partition, all data on the drive – including partitions – will be erased anyway.

A Use Case for Conditional Bean Wiring

Suppose we want to enable caching for our web application. We are interested to find out whether this helps our application or whether the overhead will so big that it actually slows our application down. We decide we want to put the new functionality behind a feature toggle. We add a new property to our application called app.caching.enabled=false. When we are ready to enable the caching, we change the property’s value to true and we are in business. When the results disappoint, we can easily revert the property’s value to false.

@Conditional Introduction

The @Conditional annotation can be used on any type or method that declares a bean:

@Conditional takes a mandatory class that implements the functional interface Condition. Condition defines a single method matches that returns a boolean. The method decides whether the bean should be loaded into the Spring context or whether it should be ignored:

publicSomeConditionimplementsCondition{publicbooleanmatches(ConditionContextcontext,AnnotatedTypeMetadatametadata){/* make decision based on context and metadata */}}

A @Conditional@Configuration

When @Conditional is applied to a class which is also annotated with @Configuration, then all of the @Bean methods, @Import, @ComponentScan and other annotations will be subject to the condition. This means that when the condition evaluates to false, all of the configuration defined in that class will be ignored.

Since creating a cache carries costs with it (even an unused cache reserves space on the heap for its initial size), this is exactly what we want in our situation.

Since we are dealing with a conditional configuration instead of a regular bean, the condition class implements ConfigurationCondition instead of Condition. The ConfigurationCondition makes us implement another method that specifies at which point the condition should be evaluated. Normally, this ConfigurationPhase is set to REGISTER_BEAN, which means it checks the condition when adding a regular bean. In this case, we want it set to PARSE_CONFIGURATION, which makes Spring evaluate the condition at the moment the configuration class is parsed. If the condition does not match at that moment, the @Configuration class will not be added to the context.

If we do not want to hard-code values into our source code, we can use properties files. With the @Value annotation, Spring gives us an easy means to get properties from properties files and inject them into our code.

The @PropertySource adds a property source to Spring’s Environment. Here, the properties file is placed in the root of the classpath (and since I am using Maven default paths, that would be src/main/resources.

Declare a ConversionService to Inject Collections And Other Complex Types

We instantiate DefaultFormattingConversionService, which is “configured by default with converters and formatters appropriate for most applications”. That means that it can convert comma-separated strings to common, generic collection types, and can convert strings to dates, currencies and TimeZones, for example.

Notice that the method is declared static. ConversionService is of type BeanFactoryPostProcessor and must be instantiated very early in the Spring container lifecycle, so that its services are available when processing of annotations such as @Autowired and @Value are done. By declaring the method static, the ConversionService can be invoked without instantiating the enclosing @Configuration class. Therefore, we can use @Value (and other annotations) that make use of this converter in the same class, without running into the trouble that ConversionService is not yet instantiated.

To convert dates from a properties string to actual date objects we need an extra step: @DateTimeFormat. This annotation indicates the format of the date to Spring. In this case, we format our property strings to conform to ISO-8601 or DateTimeFormat.ISO.DATE_TIME:

Notice the #{...} that delimits the SpEL expression. It evaluates the string that comes from the properties files and parses it to a Map. To understand how this works, let’s have a look at what a literal map in a SpEL expression would look like:

To recap, we instantiate a bean of type LocalDate by invoking its now() static method. We inject this bean into two PositiveStreak beans using constructor injection. We reference the LocalDate bean by its id, startTime. Next, we create a bean that is a list of PositiveStreaks using the util namespace. We then inject this list into a Habit class called Running using setter injection.

For setter injection to work from XML, the setter method needs to follow Java bean conventions. This means that there should be setter method called set<PropertyName>, where the important part is that the method start with set. The name of the property itself can be something completely different from the field it is setting, Spring does not care. For example, the following would work without a hitch:

The only important thing is that the name attribute of the property element corresponds to the Property part of setProperty setter method in Java. To reiterate: The name of the field that is being set by the mutator method can be something completely different from the name attribute of the property element.

But sometimes we want to be creative with our method names if that makes the code more readable, or maybe we are dealing with code that we cannot change. If we end up with a mutator method that does not start with set, you are now in a position to appreciate that Spring will not find this method and throws a BeanCreationException.

(Notice that we actually use setter injection on the MethodInvokingBean by specifying properties on it.) The targetObject attribute specifies on which instance a targetMethod should be invoked. We can specify our custom mutator name, and pass a reference to our arguments.

This is verbose, so think carefully before you violate the Java bean naming convention. Consider using a facade if the code is not under your control. Alternatively, Java-based Spring configuration with the @Autowired annotation will work on a method with any name.

If you have to work with legacy Spring applications, chances are you will have know how XML-based configuration works. Although Java configuration is preferred for new applications, sometimes you just don’t have a choice.

This would wire a bean with the id running that is of type Running (which is a Habit). You can see why this is much more of a hassle to set up than using a simple @Component annotation on a class or a @Bean annotation in a @Configuration class. Those XML namespaces are nasty, but luckily most IDEs will help you with them.

Injecting Beans

To inject dependencies, we have two choices:

Constructor injection

Setter injection

Unlike with Java configuration, we cannot insert into fields when using XML-based configuration.

Constructor Injection

Suppose we want to insert one bean into another bean, for instance a HabitRepository that persists habits to the database into a HabitService. By using the <constructor-arg /> element and the ref property, we can accomplish this:

If we wanted to pass more arguments to the HabitService constructor, we must keep on eye on the order: it must be the same as the order in which they are declared in the class.

To ease working with constructor arguments and as a way to curtail the verbosity of the XML configuration, Spring offers the c XML namespace to help wire beans without the need to create a sub-element <constructor-arg />:

We define a bean of type java.time.LocalDate and we use the static factory method now() to get an instance of it. We then use the c namespace to pass it to the constructor of our PositiveStreak bean. c:startTime-ref="currentTime" should be read as: pass the reference to the bean with id currentTime to the constructor argument that has the name startTime.

So we can reference constructor arguments by name. We can also reference them by position. c:_0-ref="currentTime" would do the exact same thing. XML does not allow a digit as the first character of an attribute, so we have to use an underscore. If there is only a single argument to the constructor, we can even use the shorthand c:_-ref="currentTime". I would not want to promote this as readable, but it’s good to know it exists and might be used in the wild.

The <property> element has an attribute name that refers to the field name of the bean being set. In the current case, class Running has a field named streaks. As a child element of <property> we define a list of Streak references.

The usage of the p namespace is a lot like that of the c namespace. In this case, p:streaks-ref="streak" tells spring to wire a property named streaks with the bean that is referenced by the id streak. Now, the property streaks takes a List. If we pass only a single element to that list, the current syntax works and Spring will happily insert the single reference to streak into a List for us and pass that to the setter method. If we want to pass more than one element in a list, however, we have to create the list separately first, and then pass the id of that reference to the p property:

We need to add the util namespace and the location of the util schema definition to get this to work. You see that the XML becomes quite verbose the more you try to do with it. The util namespace allows us to create collections of literal values or beans. These collections can then be referenced by their id.

spring-test contains the SpringRunner JUnit runner, and the @ContextConfiguration that will tell Spring where to look for the application context that contains the beans that need to be wired. In this case, we tell it to look at the applicationContext.xml that we put in src/main/resources, so we can reference it by looking at the root of our classpath with the attribute locations = "classpath:applicationContext.xml".