0

I have a bash script which checks if a swap exists or not and if it doesn't exists, then it creates one;

if free | awk '/^Swap:/ {exit !$2}'; then
    echo "Have swap, skipping"
    sudo swapoff -a
    sudo dd if=/dev/zero of=/swapfile bs=1M count=2048
    sudo mkswap /swapfile
    sudo swapon /swapfile
else
    fallocate -l 2G /swapfile
    chmod 600 /swapfile
    mkswap /swapfile
    swapon /swapfile
    sudo echo -e "/swapfile none swap sw 0 0 \n" >> /etc/fstab
fi

Now I also want to add this a check to find out the swap size - if it already exists - because if the swap already exists and it is 4GB then I will downgrade it to 2GB instead of skipping.

How can I do this?

Edit: The script currently creates a 2GB of swap file whether it exists or not so if I have 4GB swap file, it will change it to 2GB but if I also have 2GB swap file it will still re-do the swap with 2GB. I thought this is not a good option to go with so that's why I wonder if I should add a swap size check or not?

  • Why not always do a swapoff and fallocate followed by swapon? While properly catching any failed command, of course. – Kusalananda Feb 22 at 9:34
  • I'm not sure what do you mean – Marry Jane Feb 22 at 9:41
  • I'm suggesting, and it's only a suggestion (because I don't know what your system is doing, and it may be inappropriate or impossible), that you always create a 2 Gb swap file, regardless of whether one existed before or what its previous size was. – Kusalananda Feb 22 at 9:49
  • Am I? I thought I was checking if whether a swap exists or not and then create one if it doesn't exists. See the first if condition in my code? – Marry Jane Feb 22 at 9:55
  • Re-read my comments. I'm never saying that you are or aren't doing something. I'm suggesting. – Kusalananda Feb 22 at 9:58
1

Assuming your kernel is not really old and supports the fallocate system call (available since version 2.6.23, see man fallocate(1) and man fallocate(2)), fallocate will likely be fast, since it does not write data blocks. Hence, there is no big issue with always creating a new swap file. The only step you will likely want to perform conditionally is editing your fstab.

Assuming you either have no swap at all or have exactly one swap file whose path is /swapfile:

swapfile="/swapfile"

# Make sure swap is on
swapon --all

# Check if our assumptions hold
if    [ "$(swapon --show --noheadings | wc -l)" -gt 1 ]         ||
  (   [ "$(swapon --show --noheadings | wc -l)" -eq 1 ]         &&
    ( [ "$(swapon --show=TYPE --noheadings)" != 'file' ]        ||
      [ "$(swapon --show=NAME --noheadings)" != "$swapfile" ]
    )
  );  then
    echo "Unsafe to proceed, exiting."
    exit
fi

# Edit /etc/fstab if our file is not already there
if ! grep -q '^[[:blank:]]*'"$swapfile"'[[:blank:]]\{1,\}none[[:blank:]]\{1,\}swap[[:blank:]]\{1,\}' /etc/fstab;
then
    printf '%s\n' "$swapfile none swap sw 0 0" >> /etc/fstab
fi

# Create/replace the swap file
swapoff --all
[ -f "$swapfile" ] && rm -- "$swapfile"
fallocate -l 2GiB -- "$swapfile"
chmod 600 "$swapfile"
mkswap -- "$swapfile"
swapon --all

You may still want to avoid unnecessarily turning off and on your swap: it may be a slow operation if a substantial fraction of it is used and it can have unwanted consequences if not enough memory is available.
To partially address these concerns (and also answer your original question), the last part of the above code can be enclosed in a conditional block:

# Check if we want to shrink the swap file i.e. it is bigger than 2 GiB
# (or if we have no swap file)
if  [ "$(free | awk '/^Swap:/ { print $2 }')" = "0" ] ||
    [ "$(free --bytes | awk '/^Swap:/ { print $2 }')" -gt 2147483648 ]; then

    # Create/replace the swap file
    # Same as above...

fi

Finally, assuming your kernel version is at least 3.14 and provides MemAvailable in /proc/meminfo (whose value is reported as the available column by free, see man free(1)), you can also check if you have enough available memory before trying to turn off swap.
The last code snippet becomes:

# Do we have no swap or more swap than 2GB?
# If yes, do we have more available memory than used swap?
if  ( [ "$(free | awk '/^Swap:/ { print $2 }')" = "0" ] ||
      [ "$(free --bytes | awk '/^Swap:/ { print $2 }')" -gt 2147483648 ]
    ) &&
    [ "$(awk '/MemAvailable:/ { print $2 }' /proc/meminfo)" -gt "$(free | awk '/Swap:/ { print $3 }')" ];
then
    # Create/replace the swap file
    # Same as above...
fi

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.