So, trying to make "hibernate" work, would our more intrepid Members consider reviewing and testing the following script, with a view to possible general use by the Community?
Script [OS_Admin__CreateSwapfile.sh]:
#!/bin/sh
####################################################################################################
###
### Script to create new swapfile (with size equal to, or greater than, available RAM)
###
### Auth: Eric Marceau, Ottawa, Ontario, CANADA
### Vers: 2.1, 2025-11-31
### Lic: GPLv3
###
### Swap file was previously, and remains, defined as follows in /etc/fstab
### /swapfile none swap sw 0 0
###
####################################################################################################
####################################################################################################
###
### Function to perform all necessary steps to create a SWAP file of the required size.
###
####################################################################################################
createNewSwap()
{
echo "\n\t Creating new SWAP file '${newSwap}' ...\n"
dd status=progress if=/dev/zero of="${newSwap}" bs=1M count=$((SIZE*1024))
test $? -eq 0 || { echo "\n\t Failed 'dd' operation to create SWAP file. [A3]\n" ; exit 1 ; }
verifyContiguousBlocks
echo "\t [A3] ..."
chmod 0600 "${newSwap}"
test $? -eq 0 || { echo "\n\t Failed to set required privileges on '${newSwap}'. [A4]\n" ; exit 1 ; }
echo "\t [A4] ..."
ls -l "${newSwap}" | awk '{ printf("\t\t%s\n", $0 ) }'
#mkswap "${newSwap}" 2>&1 | awk '{ printf("\t\t%s\n", $0 ) }'
mkswap "${newSwap}"
test $? -eq 0 || { echo "\n\t Failed to format '${newSwap}' as swap partition. [A5]\n" ; exit 1 ; }
echo "\t [A5] ..."
#swapon "${newSwap}" 2>&1 | awk '{ printf("\t\t%s\n", $0 ) }'
swapon "${newSwap}"
test $? -eq 0 || { echo "\n\t Failed to enable '${newSwap}' as swap partition. [A6]\n" ; exit 1 ; }
echo "\t [A6] ..."
swapon --show 2>&1 | awk '{ printf("\t\t%s\n", $0 ) }'
echo "\t [A7] ..."
testor=`swapon --show 2>&1 | grep "${newSwap}" `
test -z "${testor}" && { echo "\n\t Failed to enable '${newSwap}' as active SWAP space. Unable to proceed. [8]\n Bye!\n" ; exit 1 ; }
touch "${goodSwap}.SUCCESS"
echo "\t [A8] ..."
newON=1
}
####################################################################################################
###
### Function to verify that the blocks assigned by dd are contiguous,
### or show which groupings of blocks are contiguous.
###
####################################################################################################
verifyContiguousBlocks()
{
fileBlocks="/tmp/$$.fileBlocks"
filefrag -v /swapfile >"${fileBlocks}"
echo ""
cat "${fileBlocks}"
tail -n +4 "${fileBlocks}" | grep -v '^/' |
awk -v rootDev="${rootUUID}" -v swap="${goodSwap}" -v resume="./resume" 'BEGIN{
getline ;
split( $2, vals, "." ) ;
begStrt=vals[1] ;
split( $3, vals, ":" ) ;
prevEnd=vals[1] ;
split( $4, vals, "." ) ;
resOffset=vals[1] ;
printf("\n\n Verifiying contiguous block segments ...\n") ;
}{
split( $2, vals, "." ) ;
curStrt=vals[1] ;
split( $3, vals, ":" ) ;
curLast=vals[1] ;
if( prevEnd+1 != curStrt ){
printf("\t %s - %s [contiguous blocks]\n", begStrt, prevEnd ) ;
begStrt=curStrt ;
} ;
prevEnd=curLast ;
}END{
printf("\t %s - %s [contiguous blocks]\n\n", begStrt, curLast ) ;
#resumeDirective=sprintf("resume=%s resume_offset=%s", rootDev, resOffset ) ;
resumeDirective=sprintf("RESUME=%s resume_offset=%s", rootDev, resOffset ) ;
printf("\n============\n IMPORTANT:\n============" ) ;
printf("\n\t ADD the following\n") ;
printf("\n\t\t \"%s\" \n", resumeDirective ) ;
printf("\n\t\t to \t\"GRUB_CMDLINE_LINUX_DEFAULT\" \n" ) ;
printf("\n\t\t in \t\"/etc/default/grub\" \n" ) ;
#printf("\n\t THEN see PDF \"HIBERNATE__AskUbuntu.pdf\" for other steps before proceeding with following instructions ...\n\n") ;
printf("\n\t THEN see \"https://askubuntu.com/questions/6769/hibernate-and-resume-from-a-swap-file/1132154#1132154\" for other steps before proceeding with following instructions ...\n\n") ;
printf("\n\t THEN re-run \t\"update-grub\".\n\n") ;
printf("%s\n\t# resume from %s\n", resumeDirective, swap ) >resume ;
printf("\n\t MOVE the file \"%s\" to the required location\n", resume ) ;
printf("\n\t\t \"/etc/initramfs-tools/conf.d/resume\" \n" ) ;
printf("\n\t THEN re-run \t\"update-initramfs -u -k all\".\n\n") ;
}'
}
####################################################################################################
###
### START of process coding
###
####################################################################################################
NoSWAP=0
goodSwap="/swapfile"
if [ ! -s "${goodSwap}" ]
then
echo "\n\t WARNING *** WARNING"
echo "\n\t This system has NO existing SWAP file named '${goodSwap}'.\n\n\t This script will create a SWAPFILE optimized for the amount of installed RAM.\n\t This is intended to support the needs of the HIBERNATE function.\n\n\t Do you wish to proceed ? [y|N] => \c" ; read ans
if [ -z "${ans}" ]
then
ans="n"
fi
case ${ans} in
y* | Y* ) ;;
* ) echo "\n\t Abandonned!\n Bye!\n" ; exit 1 ;;
esac
NoSWAP=1
fi
if [ ${NoSWAP} -eq 0 ]
then
echo "\n\t WARNING *** WARNING\n\n\t This script will replace the existing SWAPFILE with \n\t a newer swapfile optimized for the amount of installed RAM.\n\n\t Do you wish to proceed ? [y|N] => \c" ; read ans
if [ -z "${ans}" ]
then
ans="n"
fi
case ${ans} in
y* | Y* ) ;;
* ) echo "\n\t Abandonned!\n Bye!\n" ; exit 1 ;;
esac
fi
####################################################################################################
###
### Probing for eventual GRUB config changes
###
####################################################################################################
echo "\n Gathering disk info for updating GRUB configuration file later in process ..."
rootDev=`df / | grep '^/dev' | awk '{ print $1 }' | cut -f3 -d/ `
#rootUUID=`lsblk --pairs --output NAME,UUID,LABEL | grep \"${rootDev}\" | awk '{ gsub( "\"", "", $2 ) ; print $2 }' `
rootUUID=`blkid "/dev/${rootDev}" | awk '{ gsub( "\"", "", $3 ) ; print $3 }' `
lsblk --pairs --output NAME,UUID,LABEL |
grep \"${rootDev}\" |
awk '{
split( $0, vals, " " ) ;
printf("\n\t %s\n\t %s\n\t %s\n\n", vals[1], vals[2], vals[3] ) ;
}'
####################################################################################################
###
### Verifying required pre-conditions
###
####################################################################################################
### Number of GigaBYTES of RAM installed
#RAM=4
RAM=`free -h | grep '^Mem:' | awk '{ split( $2, vals, "." ) ; print vals[1]+1 ; }' `
if [ -z "${RAM}" ]
then
echo "\n\t Unable to determine the amount of installed RAM. Unable to proceed! [A1]\n Bye!\n" ; exit 1
fi
echo "\t [A1] ..."
echo "\n\t Amount of installed RAM detected => ${RAM} GB ..."
if [ ${RAM} -lt 2 ]
then
SIZE=`expr ${RAM} \* 2 `
else
SIZE=`expr ${RAM} + 2 `
fi
echo "\n\t Number of Gigabytes to be allocated => ${SIZE} GB ..."
if [ ${NoSWAP} -eq 1 ]
then
newSwap="${goodSwap}" ### Intended new swapfile
else
oldSwap="${goodSwap}" ### Name of existing SWAP file
newSwap="${goodSwap}.new" ### Initial name for new swapfile
testor=`grep "${oldSwap}" /etc/fstab | grep -v '^#' | awk '{ if( $1 == "/swapfile" ){ print $0 ; } ; }' `
if [ \( -z "${testor}" \) -o \( ! -s "${oldSwap}" \) ]
then
echo "\n\t There is no '/swapfile' entry currently existing in '/etc/fstab'. Unable to proceed! [A2]\n Bye!\n" ; exit 1
fi
echo "\t [A2] ..."
echo "\n\t Required SWAP file entry detected in '/etc/fstab'. Proceeding ..."
fi
####################################################################################################
###
### Create the new swapfile
###
####################################################################################################
if [ \( ${NoSWAP} -eq 0 \) -a \( -s "${newSwap}" \) -a \( -f "${goodSwap}.SUCCESS" \) ]
then
echo "\n\t New SWAP file, '${newSwap}', was created within last 24 hours. Using that ..."
else
createNewSwap
fi
####################################################################################################
###
### Actions required to replace the old swapfile with the new swapfile
###
####################################################################################################
if [ ${NoSWAP} -eq 0 ]
then
echo "\n\t Proceed with replacing old SWAP file with new SWAP file ? [y|N] => \c" ; read ans
if [ -z "${ans}" ]
then
ans="n"
fi
case "${ans}" in
y* | Y* ) ;;
* ) echo "\n\t Leaving both old and new swapfiles in place!\n Bye!\n" ; exit 1 ;;
esac
####################################################################################################
###
### Rename old SWAP then re-enable as active with new name
###
####################################################################################################
if [ -f "${goodSwap}.RENAMEOLD" ]
then
oldSwap="${goodSwap}.old"
echo "\t [B3] ..."
echo "\n\t Old SWAP file was already renamed as '${goodSwap}.old'. Using that ..."
else
swapoff "${oldSwap}"
test $? -eq 0 || { echo "\n\t Failed to disable '${oldSwap}' as swap partition. [B1]\n" ; exit 1 ; }
echo "\t [B1] ..."
mv -v "${oldSwap}" "${goodSwap}.old" ; RC=$?
oldSwap="${goodSwap}.old"
test ${RC} -eq 0 || { echo "\n\t Failed to disable '${oldSwap}' as swap partition. [B2]\n" ; exit 1 ; }
ls -l "${oldSwap}"
echo "\t [B2] ..."
swapon "${oldSwap}"
test $? -eq 0 || { echo "\n\t Failed to re-enable '${oldSwap}' as swap partition. [B3]\n" ; exit 1 ; }
touch "${goodSwap}.RENAMEOLD"
echo "\t [B3] ..."
fi
fi
####################################################################################################
###
### Rename new SWAP then re-enable as active with intended final name
###
####################################################################################################
if [ ${NoSWAP} -eq 0 ]
then
if [ -f "${goodSwap}.RENAMENEW" ]
then
newSwap="${goodSwap}"
echo "\t [C3] ..."
echo "\n\t New SWAP file was already enabled as '${goodSwap}'. Using that ..."
newON=0
else
swapoff "${newSwap}"
test $? -eq 0 || { echo "\n\t Failed to disable '${newSwap}' as swap partition. [C1]\n" ; exit 1 ; }
echo "\t [C1] ..."
mv -v "${newSwap}" "${goodSwap}"
test $? -eq 0 || { echo "\n\t Failed to rename '${newSwap}' as '${goodSwap}'. [C2]\n" ; exit 1 ; }
newSwap="${goodSwap}"
ls -l "${newSwap}"
echo "\t [C2] ..."
newON=1
fi
fi
if [ ${newON} -eq 1 ]
then
#swapon "${newSwap}" 2>&1 | awk '{ printf("\t\t%s\n", $0 ) }'
swapon "${newSwap}"
test $? -eq 0 || { echo "\n\t Failed to enable '${newSwap}' as swap partition. [C3]\n" ; exit 1 ; }
touch "${goodSwap}.RENAMENEW"
echo "\t [C3] ..."
fi
swapon --show
####################################################################################################
###
### Disable and optionally remove/purge old original SWAP file
###
####################################################################################################
if [ -f "${goodSwap}.PURGEDOLD" ]
then
echo "\t [D2] ..."
echo "\n\t Old SWAP file, '${oldSwap}', was already purged."
echo "\n\t Purge step completion flags (required prior to re-attempt) ? [y/N] => \c" ; read ans
if [ -z "${ans}" ]
then
ans="n"
fi
case "${ans}" in
y* | Y* )
test -f "${goodSwap}.SUCCESS" && rm -fv "${goodSwap}.SUCCESS"
test -f "${goodSwap}.RENAMEOLD" && rm -fv "${goodSwap}.RENAMEOLD"
test -f "${goodSwap}.RENAMENEW" && rm -fv "${goodSwap}.RENAMENEW"
test -f "${goodSwap}.PURGEDOLD" && rm -fv "${goodSwap}.PURGEDOLD"
test -f "${goodSwap}.COMPLETE" && rm -fv "${goodSwap}.COMPLETE"
;;
* ) echo "\n\t Leaving all step completion flags in place:"
ls -l "${goodSwap}."*
;;
esac
echo "\n Bye!\n"
exit 0
else
if [ ${NoSWAP} -eq 0 ]
then
swapoff "${oldSwap}"
test $? -eq 0 || { echo "\n\t Failed to disable '${oldSwap}' as swap partition. [D1]\n" ; exit 1 ; }
echo "\t [D1] ..."
echo "\n About to purge OLD SWAP file:"
rm -i "${oldSwap}"
test ! -s "${oldSwap}" && { echo "\n\t Old swap file, '${oldSwap}', has been purged. [D2]\n" ; }
echo "\t [D2] ..."
echo "\n DONE -- New SWAP file has replaced the old SWAP file as the active SWAP file!\n"
touch "${goodSwap}.PURGEDOLD"
else
echo "\n DONE -- New SWAP file has been created and enabled as active SWAP!\n"
fi
touch "${goodSwap}.COMPLETE"
exit 0
fi
Session Log:
root@OasisMega1:~# ./OS_Admin__CreateSwapfile.sh
WARNING *** WARNING
This system has NO existing SWAP file named '/swapfile'.
This script will create a SWAPFILE optimized for the amount of installed RAM.
This is intended to support the needs of the HIBERNATE function.
Do you wish to proceed ? [y|N] => y
Gathering disk info for updating GRUB configuration file later in process ...
NAME="sdb3"
UUID="5dcf1a96-fa2e-42f5-9a08-37fcce0f0878"
LABEL="DB001_F1"
[A1] ...
Amount of installed RAM detected => 4 GB ...
Number of Gigabytes to be allocated => 6 GB ...
Creating new SWAP file '/swapfile' ...
6409945088 bytes (6.4 GB, 6.0 GiB) copied, 60 s, 107 MB/s
6144+0 records in
6144+0 records out
6442450944 bytes (6.4 GB, 6.0 GiB) copied, 60.7201 s, 106 MB/s
Filesystem type is: ef53
File size of /swapfile is 6442450944 (1572864 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 53247: 37326848.. 37380095: 53248:
1: 53248.. 419839: 37382144.. 37748735: 366592: 37380096:
2: 419840.. 423935: 37785600.. 37789695: 4096: 37748736:
3: 423936.. 444415: 37793792.. 37814271: 20480: 37789696:
4: 444416.. 901119: 37816320.. 38273023: 456704: 37814272:
5: 901120.. 903167: 38307840.. 38309887: 2048: 38273024:
6: 903168.. 907263: 38311936.. 38316031: 4096: 38309888:
7: 907264.. 1384447: 38320128.. 38797311: 477184: 38316032:
8: 1384448.. 1413119: 38866944.. 38895615: 28672: 38797312:
9: 1413120.. 1443839: 38897664.. 38928383: 30720: 38895616:
10: 1443840.. 1567743: 38930432.. 39054335: 123904: 38928384:
11: 1567744.. 1572863: 0.. 0: 0: last,unknown_loc,delalloc,eof
/swapfile: 12 extents found
Verifiying contiguous block segments ...
0 - 1572863 [contiguous blocks]
============
IMPORTANT:
============
ADD the following
"resume=UUID=5dcf1a96-fa2e-42f5-9a08-37fcce0f0878 resume_offset=37326848"
to "GRUB_CMDLINE_LINUX_DEFAULT"
in "/etc/default/grub"
THEN see "https://askubuntu.com/questions/6769/hibernate-and-resume-from-a-swap-file/1132154#1132154" for other steps before proceeding with following instructions ...
THEN re-run "update-grub".
MOVE the file "./resume" to the required location
"/etc/initramfs-tools/conf.d/resume"
THEN re-run "update-initramfs -u -k all".
[A3] ...
[A4] ...
-rw------- 1 root root 6442450944 Nov 29 21:33 /swapfile
Setting up swapspace version 1, size = 6 GiB (6442446848 bytes)
no label, UUID=f076ae5b-3d1d-4776-b2ff-1f8ceb9b11ab
[A5] ...
[A6] ...
NAME TYPE SIZE USED PRIO
/dev/sdb10 partition 996.2M 177.1M 99
/dev/sdb11 partition 996.2M 177.3M 99
/dev/sda2 partition 2G 180.1M 99
/swapfile file 6G 0B -2
[A7] ...
[A8] ...
swapon: /swapfile: swapon failed: Device or resource busy
Failed to enable '/swapfile' as swap partition. [C3]
root@OasisMega1:~#